zngur_generator/
cpp.rs

1use std::{
2    collections::HashMap,
3    fmt::{Display, Write},
4    iter,
5};
6
7use itertools::Itertools;
8use zngur_def::{CppRef, CppValue, Mutability, RustTrait, ZngurField, ZngurMethodReceiver};
9
10use crate::{ZngurWellknownTraitData, rust::IntoCpp};
11
12#[derive(Debug)]
13pub struct CppPath(pub Vec<String>);
14
15impl CppPath {
16    fn namespace(&self) -> &[String] {
17        self.0.split_last().unwrap().1
18    }
19
20    fn emit_in_namespace(
21        &self,
22        state: &mut State,
23        f: impl FnOnce(&mut State) -> std::fmt::Result,
24    ) -> std::fmt::Result {
25        for p in self.namespace() {
26            writeln!(state, "namespace {} {{", p)?;
27        }
28        f(state)?;
29        for _ in self.namespace() {
30            writeln!(state, "}}")?;
31        }
32        Ok(())
33    }
34
35    fn name(&self) -> &str {
36        self.0.split_last().unwrap().0
37    }
38
39    fn need_header(&self) -> bool {
40        self.0.first().map(|x| x.as_str()) == Some("rust")
41            && self.0 != ["rust", "Unit"]
42            && self.0 != ["rust", "Ref"]
43            && self.0 != ["rust", "RefMut"]
44    }
45
46    pub(crate) fn from_rust_path(path: &[String]) -> CppPath {
47        CppPath(
48            iter::once("rust")
49                .chain(path.iter().map(|x| x.as_str()))
50                .map(cpp_handle_keyword)
51                .map(|x| x.to_owned())
52                .collect(),
53        )
54    }
55}
56
57impl<const N: usize> From<[&str; N]> for CppPath {
58    fn from(value: [&str; N]) -> Self {
59        CppPath(value.iter().map(|x| x.to_string()).collect())
60    }
61}
62
63impl From<&str> for CppPath {
64    fn from(value: &str) -> Self {
65        let value = value.trim();
66        CppPath(value.split("::").map(|x| x.to_owned()).collect())
67    }
68}
69
70impl Display for CppPath {
71    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72        write!(f, "::{}", self.0.iter().join("::"))
73    }
74}
75
76#[derive(Debug)]
77pub struct CppType {
78    pub path: CppPath,
79    pub generic_args: Vec<CppType>,
80}
81
82impl CppType {
83    pub fn into_ref(self) -> CppType {
84        CppType {
85            path: CppPath::from("rust::Ref"),
86            generic_args: vec![self],
87        }
88    }
89
90    fn emit_specialization_decl(&self, state: &mut State) -> std::fmt::Result {
91        if self.generic_args.is_empty() {
92            write!(state, "struct {}", self.path.name())?;
93        } else {
94            write!(
95                state,
96                "template<> struct {}< {} >",
97                self.path.name(),
98                self.generic_args.iter().join(", ")
99            )?;
100        }
101        Ok(())
102    }
103
104    fn emit_header(&self, state: &mut State) -> std::fmt::Result {
105        for x in &self.generic_args {
106            x.emit_header(state)?;
107        }
108        if !self.path.need_header() {
109            return Ok(());
110        }
111        self.path.emit_in_namespace(state, |state| {
112            if !self.generic_args.is_empty() {
113                writeln!(state, "template<typename ...T>")?;
114            }
115            writeln!(state, "struct {};", self.path.name())
116        })
117    }
118}
119
120impl Display for CppType {
121    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
122        write!(f, "{}", self.path)?;
123        if !self.generic_args.is_empty() {
124            write!(f, "< {} >", self.generic_args.iter().join(", "))?;
125        }
126        Ok(())
127    }
128}
129
130fn split_string(input: &str) -> impl Iterator<Item = String> {
131    let mut parts = Vec::new();
132    let mut current_part = String::new();
133    let mut parentheses_count = 0;
134
135    for c in input.chars() {
136        match c {
137            ',' if parentheses_count == 0 => {
138                parts.push(current_part.clone());
139                current_part.clear();
140            }
141            '<' => {
142                parentheses_count += 1;
143                current_part.push(c);
144            }
145            '>' => {
146                parentheses_count -= 1;
147                current_part.push(c);
148            }
149            _ => {
150                current_part.push(c);
151            }
152        }
153    }
154
155    if !current_part.is_empty() {
156        parts.push(current_part);
157    }
158
159    parts.into_iter()
160}
161
162impl From<&str> for CppType {
163    fn from(value: &str) -> Self {
164        let value = value.trim();
165        match value.split_once('<') {
166            None => CppType {
167                path: CppPath::from(value),
168                generic_args: vec![],
169            },
170            Some((path, generics)) => {
171                let generics = generics.strip_suffix('>').unwrap();
172                CppType {
173                    path: CppPath::from(path),
174                    generic_args: split_string(generics).map(|x| CppType::from(&*x)).collect(),
175                }
176            }
177        }
178    }
179}
180
181struct State {
182    text: String,
183    panic_to_exception: bool,
184}
185
186impl State {
187    fn panic_handler(&self) -> String {
188        if self.panic_to_exception {
189            r#"
190            if (__zngur_detect_panic()) {
191                __zngur_take_panic();
192                throw ::rust::Panic{};
193            }
194            "#
195            .to_owned()
196        } else {
197            "".to_owned()
198        }
199    }
200
201    fn remove_no_except_in_panic(&mut self) {
202        if self.panic_to_exception {
203            self.text = self.text.replace(" noexcept ", " ");
204        }
205    }
206}
207
208impl Write for State {
209    fn write_str(&mut self, s: &str) -> std::fmt::Result {
210        self.text += s;
211        Ok(())
212    }
213}
214
215#[derive(Debug)]
216pub struct CppTraitMethod {
217    pub name: String,
218    pub rust_link_name: String,
219    pub inputs: Vec<CppType>,
220    pub output: CppType,
221}
222
223#[derive(Debug)]
224pub struct CppFnSig {
225    pub rust_link_name: String,
226    pub inputs: Vec<CppType>,
227    pub output: CppType,
228}
229
230impl CppFnSig {
231    fn emit_rust_link(&self, state: &mut State) -> std::fmt::Result {
232        write!(state, "void {}(", self.rust_link_name)?;
233        for n in 0..self.inputs.len() {
234            write!(state, "uint8_t* i{n},")?;
235        }
236        write!(state, "uint8_t* o)")?;
237        Ok(())
238    }
239
240    fn emit_rust_link_decl(&self, state: &mut State) -> std::fmt::Result {
241        self.emit_rust_link(state)?;
242        writeln!(state, " noexcept ;")?;
243        Ok(())
244    }
245
246    fn emit_cpp_header(&self, state: &mut State, fn_name: &str) -> std::fmt::Result {
247        let CppFnSig {
248            inputs,
249            output,
250            rust_link_name: _,
251        } = self;
252        writeln!(
253            state,
254            "{output} {fn_name}({input_defs}) noexcept ;",
255            input_defs = inputs
256                .iter()
257                .enumerate()
258                .map(|(n, ty)| format!("{ty} i{n}"))
259                .join(", "),
260        )
261    }
262
263    fn emit_cpp_def(&self, state: &mut State, fn_name: &str) -> std::fmt::Result {
264        let CppFnSig {
265            inputs,
266            output,
267            rust_link_name,
268        } = self;
269        writeln!(
270            state,
271            "inline {output} {fn_name}({input_defs}) noexcept {{
272            {output} o{{}};
273            {deinits}
274            {rust_link_name}({input_args}::rust::__zngur_internal_data_ptr(o));
275            {panic_handler}
276            ::rust::__zngur_internal_assume_init(o);
277            return o;
278        }}",
279            input_defs = inputs
280                .iter()
281                .enumerate()
282                .map(|(n, ty)| format!("{ty} i{n}"))
283                .join(", "),
284            input_args = (0..inputs.len())
285                .map(|n| format!("::rust::__zngur_internal_data_ptr(i{n}), "))
286                .join(""),
287            panic_handler = state.panic_handler(),
288            deinits = (0..inputs.len())
289                .map(|n| format!("::rust::__zngur_internal_assume_deinit(i{n});"))
290                .join("\n"),
291        )
292    }
293}
294
295pub struct CppFnDefinition {
296    pub name: CppPath,
297    pub sig: CppFnSig,
298}
299
300pub struct CppExportedFnDefinition {
301    pub name: String,
302    pub sig: CppFnSig,
303}
304
305pub struct CppExportedImplDefinition {
306    pub tr: Option<CppType>,
307    pub ty: CppType,
308    pub methods: Vec<(String, CppFnSig)>,
309}
310
311impl CppFnDefinition {
312    fn emit_cpp_def(&self, state: &mut State) -> std::fmt::Result {
313        self.name.emit_in_namespace(state, |state| {
314            self.sig.emit_cpp_def(state, self.name.name())
315        })
316    }
317}
318
319#[derive(Debug)]
320pub struct CppMethod {
321    pub name: String,
322    pub kind: ZngurMethodReceiver,
323    pub sig: CppFnSig,
324}
325
326#[derive(Debug)]
327pub struct BuildFromFunction {
328    pub sig: CppFnSig,
329}
330
331#[derive(Debug)]
332pub enum CppTraitDefinition {
333    Fn {
334        sig: CppFnSig,
335    },
336    Normal {
337        as_ty: CppType,
338        methods: Vec<CppTraitMethod>,
339        link_name: String,
340        link_name_ref: String,
341    },
342}
343
344impl CppTraitDefinition {
345    fn emit_rust_links(&self, state: &mut State) -> std::fmt::Result {
346        match self {
347            CppTraitDefinition::Fn {
348                sig:
349                    CppFnSig {
350                        rust_link_name,
351                        inputs,
352                        output: _,
353                    },
354            } => {
355                writeln!(
356                    state,
357                    "void {rust_link_name}(uint8_t *data, void destructor(uint8_t *),
358                void call(uint8_t *, {} uint8_t *),
359                uint8_t *o);",
360                    (0..inputs.len()).map(|_| "uint8_t *, ").join(" ")
361                )?;
362            }
363            CppTraitDefinition::Normal {
364                link_name,
365                link_name_ref,
366                ..
367            } => {
368                writeln!(
369                    state,
370                    "void {link_name}(uint8_t *data, void destructor(uint8_t *), uint8_t *o);"
371                )?;
372                writeln!(state, "void {link_name_ref}(uint8_t *data, uint8_t *o);")?;
373            }
374        }
375        Ok(())
376    }
377
378    fn emit(&self, state: &mut State) -> std::fmt::Result {
379        let CppTraitDefinition::Normal {
380            as_ty,
381            methods,
382            link_name: _,
383            link_name_ref: _,
384        } = self
385        else {
386            return Ok(());
387        };
388        as_ty.path.emit_in_namespace(state, |state| {
389            as_ty.emit_specialization_decl(state)?;
390            write!(
391                state,
392                r#"{{
393    public:
394        virtual ~{}() {{}}
395    "#,
396                as_ty.path.name(),
397            )?;
398            for method in methods {
399                write!(
400                    state,
401                    r#"
402            virtual {output} {name}({input}) = 0;
403    "#,
404                    output = method.output,
405                    name = method.name,
406                    input = method
407                        .inputs
408                        .iter()
409                        .enumerate()
410                        .map(|(n, x)| format!("{x} i{n}"))
411                        .join(", "),
412                )?;
413            }
414            write!(
415                state,
416                r#"
417    }};
418    "#,
419            )
420        })
421    }
422
423    fn emit_cpp(&self, state: &mut State) -> std::fmt::Result {
424        match self {
425            CppTraitDefinition::Fn { .. } => (),
426            CppTraitDefinition::Normal {
427                as_ty,
428                methods,
429                link_name: _,
430                link_name_ref: _,
431            } => {
432                for method in methods {
433                    write!(state, "void {}(uint8_t* data", method.rust_link_name)?;
434                    for arg in 0..method.inputs.len() {
435                        write!(state, ", uint8_t* i{arg}")?;
436                    }
437                    writeln!(state, ", uint8_t* o) {{")?;
438                    writeln!(
439                        state,
440                        "   {as_ty}* data_typed = reinterpret_cast< {as_ty}* >(data);"
441                    )?;
442                    write!(
443                        state,
444                        "   {} oo = data_typed->{}({});",
445                        method.output,
446                        method.name,
447                        method
448                            .inputs
449                            .iter()
450                            .enumerate()
451                            .map(|(n, ty)| {
452                                format!("::rust::__zngur_internal_move_from_rust< {ty} >(i{n})")
453                            })
454                            .join(", ")
455                    )?;
456                    writeln!(state, "   ::rust::__zngur_internal_move_to_rust(o, oo);")?;
457                    writeln!(state, "}}")?;
458                }
459            }
460        }
461        Ok(())
462    }
463}
464
465#[derive(Debug, Clone, PartialEq, Eq)]
466pub enum CppLayoutPolicy {
467    StackAllocated {
468        size: usize,
469        align: usize,
470    },
471    HeapAllocated {
472        size_fn: String,
473        alloc_fn: String,
474        free_fn: String,
475    },
476    OnlyByRef,
477}
478
479#[derive(Debug)]
480pub struct CppTypeDefinition {
481    pub ty: CppType,
482    pub layout: CppLayoutPolicy,
483    pub methods: Vec<CppMethod>,
484    pub constructors: Vec<CppFnSig>,
485    pub fields: Vec<ZngurField>,
486    pub from_trait: Option<RustTrait>,
487    pub from_trait_ref: Option<RustTrait>,
488    pub wellknown_traits: Vec<ZngurWellknownTraitData>,
489    pub cpp_value: Option<CppValue>,
490    pub cpp_ref: Option<CppRef>,
491}
492
493impl Default for CppTypeDefinition {
494    fn default() -> Self {
495        Self {
496            ty: CppType::from("fill::me::you::forgot::it"),
497            layout: CppLayoutPolicy::OnlyByRef,
498            methods: vec![],
499            constructors: vec![],
500            fields: vec![],
501            wellknown_traits: vec![],
502            from_trait: None,
503            from_trait_ref: None,
504            cpp_value: None,
505            cpp_ref: None,
506        }
507    }
508}
509
510impl CppTypeDefinition {
511    fn emit_field_specialization(&self, state: &mut State) -> std::fmt::Result {
512        for field_kind in ["FieldOwned", "FieldRef", "FieldRefMut"] {
513            writeln!(
514                state,
515                r#"
516    namespace rust {{
517    template<size_t OFFSET>
518    struct {field_kind}< {ty}, OFFSET > {{
519                "#,
520                ty = self.ty,
521            )?;
522            for field in &self.fields {
523                writeln!(
524                    state,
525                    "[[no_unique_address]] {field_kind}<{}, OFFSET + {}> {};",
526                    field.ty.into_cpp(),
527                    field.offset,
528                    cpp_handle_field_name(&field.name),
529                )?;
530            }
531            for method in &self.methods {
532                if let ZngurMethodReceiver::Ref(m) = method.kind {
533                    if m == Mutability::Mut && field_kind == "FieldRef" {
534                        continue;
535                    }
536                    let CppFnSig {
537                        rust_link_name: _,
538                        inputs,
539                        output,
540                    } = &method.sig;
541                    writeln!(
542                        state,
543                        "{output} {fn_name}({input_defs}) const noexcept ;",
544                        fn_name = &method.name,
545                        input_defs = inputs
546                            .iter()
547                            .skip(1)
548                            .enumerate()
549                            .map(|(n, ty)| format!("{ty} i{n}"))
550                            .join(", "),
551                    )?;
552                }
553            }
554            writeln!(state, "}};\n}}")?;
555        }
556        Ok(())
557    }
558
559    fn emit_ref_specialization(&self, state: &mut State) -> std::fmt::Result {
560        for ref_kind in ["RefMut", "Ref"] {
561            let is_unsized = self
562                .wellknown_traits
563                .contains(&ZngurWellknownTraitData::Unsized);
564            if self.ty.path.to_string() == "::rust::Str" && ref_kind == "Ref" {
565                writeln!(
566                    state,
567                    r#"
568    auto operator""_rs(const char* input, size_t len) -> ::rust::Ref<::rust::Str>;
569"#,
570                )?;
571            }
572            if is_unsized {
573                writeln!(
574                    state,
575                    r#"
576namespace rust {{
577template<>
578struct {ref_kind}< {ty} > {{
579    {ref_kind}() {{
580        data = {{0, 0}};
581    }}
582private:
583    ::std::array<size_t, 2> data;
584    friend uint8_t* ::rust::__zngur_internal_data_ptr< ::rust::{ref_kind}< {ty} > >(const ::rust::{ref_kind}< {ty} >& t) noexcept ;
585    friend ::rust::ZngurPrettyPrinter< ::rust::{ref_kind}< {ty} > >;
586"#,
587                    ty = self.ty,
588                )?;
589            } else {
590                writeln!(
591                    state,
592                    r#"
593namespace rust {{
594template<>
595struct {ref_kind}< {ty} > {{
596    {ref_kind}() {{
597        data = 0;
598    }}
599"#,
600                    ty = self.ty,
601                )?;
602                if !matches!(self.layout, CppLayoutPolicy::OnlyByRef) {
603                    writeln!(
604                        state,
605                        r#"
606    {ref_kind}(const {ty}& t) {{
607        ::rust::__zngur_internal_check_init< {ty} >(t);
608        data = reinterpret_cast<size_t>(__zngur_internal_data_ptr(t));
609    }}
610"#,
611                        ty = self.ty,
612                    )?;
613                }
614                for field in &self.fields {
615                    writeln!(
616                        state,
617                        "[[no_unique_address]] ::rust::Field{ref_kind}<{}, {}> {};",
618                        field.ty.into_cpp(),
619                        field.offset,
620                        cpp_handle_field_name(&field.name),
621                    )?;
622                }
623                writeln!(
624                    state,
625                    r#"
626private:
627    size_t data;
628    friend uint8_t* ::rust::__zngur_internal_data_ptr< ::rust::{ref_kind}< {ty} > >(const ::rust::{ref_kind}< {ty} >& t) noexcept ;
629    friend ::rust::ZngurPrettyPrinter< ::rust::{ref_kind}< {ty} > >;
630"#,
631                    ty = self.ty,
632                )?;
633            }
634            writeln!(state, "public:")?;
635            if ref_kind == "Ref" {
636                writeln!(
637                    state,
638                    r#"
639    Ref(RefMut< {ty} > rm) {{
640        data = rm.data;
641    }}
642    "#,
643                    ty = self.ty,
644                )?;
645                if !is_unsized {
646                    writeln!(
647                        state,
648                        r#"
649    template<size_t OFFSET>
650    Ref(const FieldOwned< {ty}, OFFSET >& f) {{
651        data = reinterpret_cast<size_t>(&f) + OFFSET;
652    }}
653
654    template<size_t OFFSET>
655    Ref(const FieldRef< {ty}, OFFSET >& f) {{
656        data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
657    }}
658
659    template<size_t OFFSET>
660    Ref(const FieldRefMut< {ty}, OFFSET >& f) {{
661        data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
662    }}
663    "#,
664                        ty = self.ty,
665                    )?;
666                }
667            } else {
668                writeln!(
669                    state,
670                    r#"
671    friend Ref< {ty} >;
672    "#,
673                    ty = self.ty,
674                )?;
675                if !is_unsized {
676                    writeln!(
677                        state,
678                        r#"
679    template<size_t OFFSET>
680    RefMut(const FieldOwned< {ty}, OFFSET >& f) {{
681        data = reinterpret_cast<size_t>(&f) + OFFSET;
682    }}
683
684    template<size_t OFFSET>
685    RefMut(const FieldRefMut< {ty}, OFFSET >& f) {{
686        data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
687    }}
688    "#,
689                        ty = self.ty,
690                    )?;
691                }
692            }
693            match &self.from_trait_ref {
694                Some(RustTrait::Fn { inputs, output, .. }) => {
695                    let as_std_function = format!(
696                        "::std::function< {}({})>",
697                        output.into_cpp(),
698                        inputs.iter().map(|x| x.into_cpp()).join(", ")
699                    );
700                    writeln!(
701                        state,
702                        r#"
703inline {ty}({as_std_function} f);
704"#,
705                        ty = self.ty.path.name(),
706                    )?;
707                }
708                Some(tr @ RustTrait::Normal { .. }) => {
709                    let tr = tr.into_cpp();
710                    writeln!(
711                        state,
712                        r#"
713            inline {ref_kind}({tr}& arg);
714            "#,
715                    )?;
716                }
717                None => (),
718            }
719            if let Some(CppValue(rust_link_name, cpp_ty)) = &self.cpp_value {
720                writeln!(
721                    state,
722                    r#"
723                inline {cpp_ty}& cpp() {{
724                    return (*{rust_link_name}(reinterpret_cast<uint8_t*>(data))).as_cpp< {cpp_ty} >();
725                }}"#
726                )?;
727            }
728            if let Some(cpp_ty) = &self.cpp_ref {
729                writeln!(
730                    state,
731                    r#"
732                inline {cpp_ty}& cpp() {{
733                    return *reinterpret_cast< {cpp_ty}* >(data);
734                }}"#
735                )?;
736                writeln!(
737                    state,
738                    r#"
739                inline {ref_kind}(const {cpp_ty}& t) : data(reinterpret_cast<size_t>(&t)) {{}}"#
740                )?;
741            }
742            for method in &self.methods {
743                if let ZngurMethodReceiver::Ref(m) = method.kind {
744                    if m == Mutability::Mut && ref_kind == "Ref" {
745                        continue;
746                    }
747                    let CppFnSig {
748                        rust_link_name: _,
749                        inputs,
750                        output,
751                    } = &method.sig;
752                    writeln!(
753                        state,
754                        "{output} {fn_name}({input_defs}) const noexcept ;",
755                        fn_name = &method.name,
756                        input_defs = inputs
757                            .iter()
758                            .skip(1)
759                            .enumerate()
760                            .map(|(n, ty)| format!("{ty} i{n}"))
761                            .join(", "),
762                    )?;
763                }
764            }
765            if self.ty.path.to_string() == "::rust::Str" && ref_kind == "Ref" {
766                writeln!(
767                    state,
768                    r#"
769    friend auto ::operator""_rs(const char* input, size_t len) -> ::rust::Ref<::rust::Str>;
770}};
771"#,
772                )?;
773            } else {
774                writeln!(state, "}};")?;
775            }
776            writeln!(
777                state,
778                r#"
779template<>
780inline uint8_t* __zngur_internal_data_ptr< {ref_kind} < {ty} > >(const {ref_kind}< {ty} >& t) noexcept {{
781    return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&t.data));
782}}
783
784template<>
785inline void __zngur_internal_assume_init< {ref_kind} < {ty} > >({ref_kind}< {ty} >&) noexcept {{
786}}
787
788template<>
789inline void __zngur_internal_check_init< {ref_kind} < {ty} > >(const {ref_kind}< {ty} >&) noexcept {{
790}}
791
792template<>
793inline void __zngur_internal_assume_deinit< {ref_kind} < {ty} > >({ref_kind}< {ty} >&) noexcept {{
794}}
795
796template<>
797inline size_t __zngur_internal_size_of< {ref_kind} < {ty} > >() noexcept {{
798    return {size};
799}}
800}}"#,
801                ty = self.ty,
802                size = if is_unsized { 16 } else { 8 },
803            )?;
804            if self.ty.path.to_string() == "::rust::Str" && ref_kind == "Ref" {
805                writeln!(
806                    state,
807                    r#"
808inline ::rust::Ref<::rust::Str> operator""_rs(const char* input, size_t len) {{
809    ::rust::Ref<::rust::Str> o;
810    o.data[0] = reinterpret_cast<size_t>(input);
811    o.data[1] = len;
812    return o;
813}}
814                    "#,
815                )?;
816            }
817        }
818        Ok(())
819    }
820
821    fn emit(&self, state: &mut State) -> std::fmt::Result {
822        let is_copy = self
823            .wellknown_traits
824            .contains(&ZngurWellknownTraitData::Copy);
825        writeln!(
826            state,
827            r#"
828namespace rust {{
829    template<>
830    inline uint8_t* __zngur_internal_data_ptr< {ty} >(const {ty}& t) noexcept ;
831    template<>
832    inline void __zngur_internal_check_init< {ty} >(const {ty}& t) noexcept ;
833    template<>
834    inline void __zngur_internal_assume_init< {ty} >({ty}& t) noexcept ;
835    template<>
836    inline void __zngur_internal_assume_deinit< {ty} >({ty}& t) noexcept ;
837    template<>
838    inline size_t __zngur_internal_size_of< {ty} >() noexcept ;
839}}"#,
840            ty = self.ty,
841        )?;
842        self.ty.path.emit_in_namespace(state, |state| {
843            if self.ty.path.0 == ["rust", "Unit"] {
844                write!(
845                    state,
846                    "template<> struct Tuple<> {{ ::std::array< ::uint8_t, 1> data; }};"
847                )?;
848                return Ok(());
849            } else {
850                self.ty.emit_specialization_decl(state)?;
851            }
852            match self.layout {
853                CppLayoutPolicy::OnlyByRef => {
854                    writeln!(
855                        state,
856                        r#"
857{{
858public:
859    {ty}() = delete;
860    "#,
861                        ty = self.ty.path.name(),
862                    )?;
863                }
864                CppLayoutPolicy::HeapAllocated { .. } | CppLayoutPolicy::StackAllocated { .. } => {
865                    match self.layout {
866                        CppLayoutPolicy::StackAllocated { size, align } => {
867                            writeln!(
868                                state,
869                                r#"
870{{
871private:
872    alignas({align}) mutable ::std::array<uint8_t, {size}> data;
873            "#,
874                            )?;
875                        }
876                        CppLayoutPolicy::HeapAllocated { .. } => {
877                            writeln!(
878                                state,
879                                r#"
880{{
881private:
882    uint8_t* data;
883            "#,
884                            )?;
885                        }
886                        CppLayoutPolicy::OnlyByRef => unreachable!(),
887                    }
888                    writeln!(
889                        state,
890                        r#"
891    friend uint8_t* ::rust::__zngur_internal_data_ptr< {ty} >(const {ty}& t) noexcept ;
892    friend void ::rust::__zngur_internal_check_init< {ty} >(const {ty}& t) noexcept ;
893    friend void ::rust::__zngur_internal_assume_init< {ty} >({ty}& t) noexcept ;
894    friend void ::rust::__zngur_internal_assume_deinit< {ty} >({ty}& t) noexcept ;
895    friend ::rust::ZngurPrettyPrinter< {ty} >;
896"#,
897                        ty = self.ty,
898                    )?;
899                    if self.ty.path.to_string() == "::rust::Bool" {
900                        assert_eq!(
901                            self.layout,
902                            CppLayoutPolicy::StackAllocated { size: 1, align: 1 }
903                        );
904                        assert!(is_copy);
905                        writeln!(
906                            state,
907                            r#"
908public:
909    operator bool() {{
910        return data[0];
911    }}
912    Bool(bool b) {{
913        data[0] = b;
914    }}
915private:
916    "#,
917                        )?;
918                    }
919                    if !is_copy {
920                        writeln!(state, "   bool drop_flag;")?;
921                    }
922                    let (alloc_heap, free_heap, copy_data) = match &self.layout {
923                        CppLayoutPolicy::StackAllocated { .. } => (
924                            "".to_owned(),
925                            "".to_owned(),
926                            "this->data = other.data;".to_owned(),
927                        ),
928                        CppLayoutPolicy::HeapAllocated {
929                            size_fn,
930                            alloc_fn,
931                            free_fn,
932                        } => (
933                            format!("data = {alloc_fn}();"),
934                            format!("{free_fn}(data);"),
935                            format!("memcpy(this->data, other.data, {size_fn}());"),
936                        ),
937                        CppLayoutPolicy::OnlyByRef => unreachable!(),
938                    };
939                    writeln!(state, "public:")?;
940                    if is_copy {
941                        writeln!(
942                            state,
943                            r#"
944    {ty}() {{ {alloc_heap} }}
945    ~{ty}() {{ {free_heap} }}
946    {ty}(const {ty}& other) {{
947        {alloc_heap}
948        {copy_data}
949    }}
950    {ty}& operator=(const {ty}& other) {{
951        {copy_data}
952        return *this;
953    }}
954    {ty}({ty}&& other) {{
955        {alloc_heap}
956        {copy_data}
957    }}
958    {ty}& operator=({ty}&& other) {{
959        {copy_data}
960        return *this;
961    }}
962    "#,
963                            ty = self.ty.path.name(),
964                        )?;
965                    } else {
966                        let drop_in_place = self
967                            .wellknown_traits
968                            .iter()
969                            .find_map(|x| match x {
970                                ZngurWellknownTraitData::Drop { drop_in_place } => {
971                                    Some(drop_in_place)
972                                }
973                                _ => None,
974                            })
975                            .unwrap();
976                        writeln!(
977                            state,
978                            r#"
979    {ty}() : drop_flag(false) {{ {alloc_heap} }}
980    ~{ty}() {{
981        if (drop_flag) {{
982            {drop_in_place}(&data[0]);
983        }}
984        {free_heap}
985    }}
986    {ty}(const {ty}& other) = delete;
987    {ty}& operator=(const {ty}& other) = delete;
988    {ty}({ty}&& other) : drop_flag(false) {{
989        {alloc_heap}
990        *this = ::std::move(other);
991    }}
992    {ty}& operator=({ty}&& other) {{
993        if (this != &other)
994        {{
995            if (drop_flag) {{
996                {drop_in_place}(&data[0]);
997            }}
998            this->drop_flag = other.drop_flag;
999            {copy_data}
1000            other.drop_flag = false;
1001        }}
1002        return *this;
1003    }}
1004    "#,
1005                            ty = self.ty.path.name(),
1006                        )?;
1007                    }
1008                    match &self.from_trait {
1009                        Some(RustTrait::Fn { inputs, output, .. }) => {
1010                            let as_std_function = format!(
1011                                "::std::function< {}({})>",
1012                                output.into_cpp(),
1013                                inputs.iter().map(|x| x.into_cpp()).join(", ")
1014                            );
1015                            writeln!(
1016                                state,
1017                                r#"
1018    static inline {ty} make_box({as_std_function} f);
1019    "#,
1020                                ty = self.ty.path.name(),
1021                            )?;
1022                        }
1023                        Some(RustTrait::Normal { .. }) => {
1024                            writeln!(
1025                                state,
1026                                r#"
1027                        template<typename T, typename... Args>
1028                        static {ty} make_box(Args&&... args);
1029                        "#,
1030                                ty = self.ty.path.name(),
1031                            )?;
1032                        }
1033                        None => (),
1034                    }
1035                }
1036            }
1037            if let Some(CppValue(rust_link_name, cpp_ty)) = &self.cpp_value {
1038                writeln!(
1039                    state,
1040                    r#"
1041                    inline {cpp_ty}& cpp() {{
1042                        return (*{rust_link_name}(&data[0])).as_cpp< {cpp_ty} >();
1043                    }}"#
1044                )?;
1045            }
1046            for method in &self.methods {
1047                write!(state, "static ")?;
1048                method.sig.emit_cpp_header(state, &method.name)?;
1049                if method.kind != ZngurMethodReceiver::Static {
1050                    let CppFnSig {
1051                        rust_link_name: _,
1052                        inputs,
1053                        output,
1054                    } = &method.sig;
1055                    writeln!(
1056                        state,
1057                        "{output} {fn_name}({input_defs}) {const_kw} noexcept ;",
1058                        fn_name = &method.name,
1059                        input_defs = inputs
1060                            .iter()
1061                            .skip(1)
1062                            .enumerate()
1063                            .map(|(n, ty)| format!("{ty} i{n}"))
1064                            .join(", "),
1065                        const_kw = if method.kind != ZngurMethodReceiver::Ref(Mutability::Not) {
1066                            ""
1067                        } else {
1068                            "const"
1069                        },
1070                    )?;
1071                }
1072            }
1073            for constructor in &self.constructors {
1074                writeln!(
1075                    state,
1076                    "{fn_name}({input_defs}) noexcept ;",
1077                    fn_name = &self.ty.path.0.last().unwrap(),
1078                    input_defs = constructor
1079                        .inputs
1080                        .iter()
1081                        .enumerate()
1082                        .map(|(n, ty)| format!("{ty} i{n}"))
1083                        .join(", "),
1084                )?;
1085            }
1086            for field in &self.fields {
1087                writeln!(
1088                    state,
1089                    "[[no_unique_address]] ::rust::FieldOwned<{}, {}> {};",
1090                    field.ty.into_cpp(),
1091                    field.offset,
1092                    cpp_handle_field_name(&field.name),
1093                )?;
1094            }
1095            writeln!(state, "}};")
1096        })?;
1097        let ty = &self.ty;
1098        if self.layout != CppLayoutPolicy::OnlyByRef {
1099            match &self.layout {
1100                CppLayoutPolicy::StackAllocated { size, align: _ } => {
1101                    writeln!(
1102                        state,
1103                        r#"
1104namespace rust {{
1105    template<>
1106    inline size_t __zngur_internal_size_of< {ty} >() noexcept {{
1107        return {size};
1108    }}
1109        "#,
1110                    )?;
1111                }
1112                CppLayoutPolicy::HeapAllocated { size_fn, .. } => {
1113                    writeln!(
1114                        state,
1115                        r#"
1116namespace rust {{
1117    template<>
1118    inline size_t __zngur_internal_size_of< {ty} >() noexcept {{
1119        return {size_fn}();
1120    }}
1121        "#,
1122                    )?;
1123                }
1124                CppLayoutPolicy::OnlyByRef => unreachable!(),
1125            }
1126
1127            if is_copy {
1128                writeln!(
1129                    state,
1130                    r#"
1131        template<>
1132        inline void __zngur_internal_check_init< {ty} >(const {ty}&) noexcept {{
1133        }}
1134
1135        template<>
1136        inline void __zngur_internal_assume_init< {ty} >({ty}&) noexcept {{
1137        }}
1138
1139        template<>
1140        inline void __zngur_internal_assume_deinit< {ty} >({ty}&) noexcept {{
1141        }}
1142"#,
1143                )?;
1144            } else {
1145                writeln!(
1146                    state,
1147                    r#"
1148        template<>
1149        inline void __zngur_internal_check_init< {ty} >(const {ty}& t) noexcept {{
1150            if (!t.drop_flag) {{
1151                ::std::cerr << "Use of uninitialized or moved Zngur Rust object with type {ty}" << ::std::endl;
1152                while (true) raise(SIGSEGV);
1153            }}
1154        }}
1155
1156        template<>
1157        inline void __zngur_internal_assume_init< {ty} >({ty}& t) noexcept {{
1158            t.drop_flag = true;
1159        }}
1160
1161        template<>
1162        inline void __zngur_internal_assume_deinit< {ty} >({ty}& t) noexcept {{
1163            ::rust::__zngur_internal_check_init< {ty} >(t);
1164            t.drop_flag = false;
1165        }}
1166"#,
1167                )?;
1168            }
1169            writeln!(
1170                state,
1171                r#"
1172    template<>
1173    inline uint8_t* __zngur_internal_data_ptr< {ty} >({ty} const & t) noexcept {{
1174        return const_cast<uint8_t*>(&t.data[0]);
1175    }}
1176}}
1177"#,
1178            )?;
1179        }
1180        self.emit_ref_specialization(state)?;
1181        self.emit_field_specialization(state)?;
1182        Ok(())
1183    }
1184
1185    fn emit_cpp_fn_defs(
1186        &self,
1187        state: &mut State,
1188        traits: &HashMap<RustTrait, CppTraitDefinition>,
1189    ) -> std::fmt::Result {
1190        let is_unsized = self
1191            .wellknown_traits
1192            .contains(&ZngurWellknownTraitData::Unsized);
1193        let cpp_type = &self.ty.to_string();
1194        let my_name = cpp_type.strip_prefix("::").unwrap();
1195        for c in &self.constructors {
1196            let fn_name = my_name.to_owned() + "::" + self.ty.path.0.last().unwrap();
1197            let CppFnSig {
1198                inputs,
1199                output: _,
1200                rust_link_name,
1201            } = c;
1202            writeln!(
1203                state,
1204                "inline {fn_name}({input_defs}) noexcept {{
1205            ::rust::__zngur_internal_assume_init(*this);
1206            {rust_link_name}({input_args}::rust::__zngur_internal_data_ptr(*this));
1207            {deinits}
1208        }}",
1209                input_defs = inputs
1210                    .iter()
1211                    .enumerate()
1212                    .map(|(n, ty)| format!("{ty} i{n}"))
1213                    .join(", "),
1214                input_args = (0..inputs.len())
1215                    .map(|n| format!("::rust::__zngur_internal_data_ptr(i{n}), "))
1216                    .join(""),
1217                deinits = (0..inputs.len())
1218                    .map(|n| format!("::rust::__zngur_internal_assume_deinit(i{n});"))
1219                    .join("\n"),
1220            )?;
1221        }
1222        match self.from_trait.as_ref().and_then(|k| traits.get(k)) {
1223            Some(CppTraitDefinition::Fn { sig }) => {
1224                let as_std_function = format!(
1225                    "::std::function< {}({})>",
1226                    sig.output,
1227                    sig.inputs.iter().join(", ")
1228                );
1229                let ii_names = sig
1230                    .inputs
1231                    .iter()
1232                    .enumerate()
1233                    .map(|(n, x)| format!("::rust::__zngur_internal_move_from_rust< {x} >(i{n})"))
1234                    .join(", ");
1235                let uint8_t_ix = sig
1236                    .inputs
1237                    .iter()
1238                    .enumerate()
1239                    .map(|(n, _)| format!("uint8_t* i{n},"))
1240                    .join(" ");
1241                let out_ty = &sig.output;
1242                writeln!(
1243                    state,
1244                    r#"
1245{my_name} {my_name}::make_box({as_std_function} f) {{
1246auto data = new {as_std_function}(f);
1247{my_name} o;
1248::rust::__zngur_internal_assume_init(o);
1249{link_name}(
1250reinterpret_cast<uint8_t*>(data),
1251[](uint8_t *d) {{ delete reinterpret_cast< {as_std_function}*>(d); }},
1252[](uint8_t *d, {uint8_t_ix} uint8_t *o) {{
1253auto dd = reinterpret_cast< {as_std_function} *>(d);
1254{out_ty} oo = (*dd)({ii_names});
1255::rust::__zngur_internal_move_to_rust< {out_ty} >(o, oo);
1256}},
1257::rust::__zngur_internal_data_ptr(o));
1258return o;
1259}}
1260"#,
1261                    link_name = sig.rust_link_name,
1262                )?;
1263            }
1264            Some(CppTraitDefinition::Normal {
1265                as_ty,
1266                methods: _,
1267                link_name,
1268                link_name_ref: _,
1269            }) => {
1270                writeln!(
1271                    state,
1272                    r#"
1273template<typename T, typename... Args>
1274{my_name} {my_name}::make_box(Args&&... args) {{
1275auto data = new T(::std::forward<Args>(args)...);
1276auto data_as_impl = dynamic_cast< {as_ty}*>(data);
1277{my_name} o;
1278::rust::__zngur_internal_assume_init(o);
1279{link_name}(
1280reinterpret_cast<uint8_t*>(data_as_impl),
1281[](uint8_t *d) {{ delete reinterpret_cast< {as_ty} *>(d); }},
1282"#,
1283                )?;
1284                writeln!(
1285                    state,
1286                    r#"
1287::rust::__zngur_internal_data_ptr(o));
1288return o;
1289}}
1290"#,
1291                )?;
1292            }
1293            None => (),
1294        }
1295        match self.from_trait_ref.as_ref().and_then(|k| traits.get(k)) {
1296            Some(CppTraitDefinition::Fn { .. }) => {
1297                todo!()
1298            }
1299            Some(CppTraitDefinition::Normal {
1300                as_ty,
1301                methods: _,
1302                link_name: _,
1303                link_name_ref,
1304            }) => {
1305                for ref_kind in ["Ref", " RefMut"] {
1306                    writeln!(
1307                        state,
1308                        r#"
1309rust::{ref_kind}< {my_name} >::{ref_kind}({as_ty}& args) {{
1310auto data_as_impl = &args;
1311::rust::__zngur_internal_assume_init(*this);
1312{link_name_ref}(
1313(uint8_t *)data_as_impl,
1314"#,
1315                    )?;
1316                    writeln!(
1317                        state,
1318                        r#"
1319::rust::__zngur_internal_data_ptr(*this));
1320}}
1321"#,
1322                    )?;
1323                }
1324            }
1325            None => (),
1326        }
1327        for method in &self.methods {
1328            let fn_name = my_name.to_owned() + "::" + &method.name;
1329            method.sig.emit_cpp_def(state, &fn_name)?;
1330            if let ZngurMethodReceiver::Ref(m) = method.kind {
1331                let ref_kinds: &[&str] = match m {
1332                    Mutability::Mut => &["RefMut"],
1333                    Mutability::Not => &["Ref", "RefMut"],
1334                };
1335                let field_kinds: &[&str] = match m {
1336                    Mutability::Mut => &["FieldOwned", "FieldRefMut"],
1337                    Mutability::Not => &["FieldOwned", "FieldRefMut", "FieldRef"],
1338                };
1339                for field_kind in field_kinds {
1340                    let CppFnSig {
1341                        rust_link_name: _,
1342                        inputs,
1343                        output,
1344                    } = &method.sig;
1345                    writeln!(
1346                        state,
1347                        "template<size_t OFFSET>
1348                        inline {output} rust::{field_kind}< {ty}, OFFSET >::{method_name}({input_defs}) const noexcept {{
1349                    return {fn_name}(*this{input_args});
1350                }}",
1351                        ty = &self.ty,
1352                        method_name = &method.name,
1353                        input_defs = inputs
1354                            .iter()
1355                            .skip(1)
1356                            .enumerate()
1357                            .map(|(n, ty)| format!("{ty} i{n}"))
1358                            .join(", "),
1359                        input_args = (0..inputs.len() - 1)
1360                            .map(|n| format!(", ::std::move(i{n})"))
1361                            .join("")
1362                    )?;
1363                }
1364                for ref_kind in ref_kinds {
1365                    let CppFnSig {
1366                        rust_link_name: _,
1367                        inputs,
1368                        output,
1369                    } = &method.sig;
1370                    writeln!(
1371                        state,
1372                        "inline {output} rust::{ref_kind}< {ty} >::{method_name}({input_defs}) const noexcept {{
1373                    return {fn_name}(*this{input_args});
1374                }}",
1375                        ty = &self.ty,
1376                        method_name = &method.name,
1377                        input_defs = inputs
1378                            .iter()
1379                            .skip(1)
1380                            .enumerate()
1381                            .map(|(n, ty)| format!("{ty} i{n}"))
1382                            .join(", "),
1383                        input_args = (0..inputs.len() - 1)
1384                            .map(|n| format!(", ::std::move(i{n})"))
1385                            .join("")
1386                    )?;
1387                }
1388            }
1389            if !is_unsized
1390                && !matches!(self.layout, CppLayoutPolicy::OnlyByRef)
1391                && method.kind != ZngurMethodReceiver::Static
1392            {
1393                let CppFnSig {
1394                    rust_link_name: _,
1395                    inputs,
1396                    output,
1397                } = &method.sig;
1398                writeln!(
1399                    state,
1400                    "inline {output} {fn_name}({input_defs}) {const_kw} noexcept {{
1401                    return {fn_name}({this_arg}{input_args});
1402                }}",
1403                    this_arg = match method.kind {
1404                        ZngurMethodReceiver::Ref(_) => "*this",
1405                        ZngurMethodReceiver::Move => "::std::move(*this)",
1406                        ZngurMethodReceiver::Static => unreachable!(),
1407                    },
1408                    input_defs = inputs
1409                        .iter()
1410                        .skip(1)
1411                        .enumerate()
1412                        .map(|(n, ty)| format!("{ty} i{n}"))
1413                        .join(", "),
1414                    input_args = (0..inputs.len() - 1)
1415                        .map(|n| format!(", ::std::move(i{n})"))
1416                        .join(""),
1417                    const_kw = if method.kind != ZngurMethodReceiver::Ref(Mutability::Not) {
1418                        ""
1419                    } else {
1420                        "const"
1421                    },
1422                )?;
1423            }
1424        }
1425        let is_unsized = self
1426            .wellknown_traits
1427            .contains(&ZngurWellknownTraitData::Unsized);
1428        for tr in &self.wellknown_traits {
1429            match tr {
1430                ZngurWellknownTraitData::Debug {
1431                    pretty_print,
1432                    debug_print: _, // TODO: use it
1433                } => {
1434                    if !is_unsized {
1435                        writeln!(
1436                            state,
1437                            r#"
1438            namespace rust {{
1439                template<>
1440                struct ZngurPrettyPrinter< {ty} > {{
1441                    static inline void print({ty} const& t) {{
1442                        ::rust::__zngur_internal_check_init< {ty} >(t);
1443                        {pretty_print}(&t.data[0]);
1444                    }}
1445                }};
1446
1447                template<>
1448                struct ZngurPrettyPrinter< Ref< {ty} > > {{
1449                    static inline void print(Ref< {ty} > const& t) {{
1450                        ::rust::__zngur_internal_check_init< Ref< {ty} > >(t);
1451                        {pretty_print}(reinterpret_cast<uint8_t*>(t.data));
1452                    }}
1453                }};
1454
1455                template<>
1456                struct ZngurPrettyPrinter< RefMut< {ty} > > {{
1457                    static inline void print(RefMut< {ty} > const& t) {{
1458                        ::rust::__zngur_internal_check_init< RefMut< {ty} > >(t);
1459                        {pretty_print}(reinterpret_cast<uint8_t*>(t.data));
1460                    }}
1461                }};
1462
1463                template<size_t OFFSET>
1464                struct ZngurPrettyPrinter< FieldOwned< {ty}, OFFSET > > {{
1465                    static inline void print(FieldOwned< {ty}, OFFSET > const& t) {{
1466                        ZngurPrettyPrinter< Ref< {ty} > >::print(t);
1467                    }}
1468                }};
1469
1470                template<size_t OFFSET>
1471                struct ZngurPrettyPrinter< FieldRef< {ty}, OFFSET > > {{
1472                    static inline void print(FieldRef< {ty}, OFFSET > const& t) {{
1473                        ZngurPrettyPrinter< Ref< {ty} > >::print(t);
1474                    }}
1475                }};
1476
1477                template<size_t OFFSET>
1478                struct ZngurPrettyPrinter< FieldRefMut< {ty}, OFFSET > > {{
1479                    static inline void print(FieldRefMut< {ty}, OFFSET > const& t) {{
1480                        ZngurPrettyPrinter< Ref< {ty} > >::print(t);
1481                    }}
1482                }};
1483            }}"#,
1484                            ty = self.ty,
1485                        )?;
1486                    } else {
1487                        writeln!(
1488                            state,
1489                            r#"
1490            namespace rust {{
1491                template<>
1492                struct ZngurPrettyPrinter< Ref< {ty} > > {{
1493                    static inline void print(Ref< {ty} > const& t) {{
1494                        ::rust::__zngur_internal_check_init< Ref< {ty} > >(t);
1495                        {pretty_print}(::rust::__zngur_internal_data_ptr< Ref< {ty} > >(t));
1496                    }}
1497                }};
1498
1499                template<>
1500                struct ZngurPrettyPrinter< RefMut< {ty} > > {{
1501                    static inline void print(RefMut< {ty} > const& t) {{
1502                        ::rust::__zngur_internal_check_init< RefMut< {ty} > >(t);
1503                        {pretty_print}(::rust::__zngur_internal_data_ptr< RefMut< {ty} > >(t));
1504                    }}
1505                }};
1506            }}"#,
1507                            ty = self.ty,
1508                        )?;
1509                    }
1510                }
1511                ZngurWellknownTraitData::Unsized
1512                | ZngurWellknownTraitData::Copy
1513                | ZngurWellknownTraitData::Drop { .. } => {}
1514            }
1515        }
1516        Ok(())
1517    }
1518
1519    fn emit_rust_links(&self, state: &mut State) -> std::fmt::Result {
1520        for method in &self.methods {
1521            method.sig.emit_rust_link_decl(state)?;
1522        }
1523        for c in &self.constructors {
1524            c.emit_rust_link_decl(state)?;
1525        }
1526        if let Some(cpp_value) = &self.cpp_value {
1527            writeln!(
1528                state,
1529                "::rust::ZngurCppOpaqueOwnedObject* {}(uint8_t*);",
1530                cpp_value.0
1531            )?;
1532        }
1533        if let CppLayoutPolicy::HeapAllocated {
1534            size_fn,
1535            alloc_fn,
1536            free_fn,
1537        } = &self.layout
1538        {
1539            writeln!(state, "size_t {size_fn}();")?;
1540            writeln!(state, "uint8_t* {alloc_fn}();")?;
1541            writeln!(state, "void {free_fn}(uint8_t*);")?;
1542        }
1543        for tr in &self.wellknown_traits {
1544            match tr {
1545                ZngurWellknownTraitData::Debug {
1546                    pretty_print,
1547                    debug_print,
1548                } => {
1549                    writeln!(state, "void {pretty_print}(uint8_t *data);")?;
1550                    writeln!(state, "void {debug_print}(uint8_t *data);")?;
1551                }
1552                ZngurWellknownTraitData::Unsized | ZngurWellknownTraitData::Copy => (),
1553                ZngurWellknownTraitData::Drop { drop_in_place } => {
1554                    writeln!(state, "void {drop_in_place}(uint8_t *data);")?;
1555                }
1556            }
1557        }
1558        Ok(())
1559    }
1560}
1561
1562#[derive(Default)]
1563pub struct CppFile {
1564    pub type_defs: Vec<CppTypeDefinition>,
1565    pub trait_defs: HashMap<RustTrait, CppTraitDefinition>,
1566    pub fn_defs: Vec<CppFnDefinition>,
1567    pub exported_fn_defs: Vec<CppExportedFnDefinition>,
1568    pub exported_impls: Vec<CppExportedImplDefinition>,
1569    pub additional_includes: String,
1570    pub panic_to_exception: bool,
1571}
1572
1573impl CppFile {
1574    fn emit_h_file(&self, state: &mut State) -> std::fmt::Result {
1575        state.text += r#"
1576#pragma once
1577
1578#include <cstddef>
1579#include <cstdint>
1580#include <cstring>
1581#include <csignal>
1582#include <array>
1583#include <iostream>
1584#include <functional>
1585#include <math.h>
1586"#;
1587        state.text += &self.additional_includes;
1588        if self.panic_to_exception {
1589            state.text += r#"
1590            namespace rust {
1591                class Panic {};
1592            }
1593            extern "C" {
1594                uint8_t __zngur_detect_panic();
1595                void __zngur_take_panic();
1596            }
1597            "#;
1598        }
1599        state.text += r#"
1600#define zngur_dbg(x) (::rust::zngur_dbg_impl(__FILE__, __LINE__, #x, x))
1601
1602namespace rust {
1603    template<typename T>
1604    uint8_t* __zngur_internal_data_ptr(const T& t) noexcept ;
1605
1606    template<typename T>
1607    void __zngur_internal_assume_init(T& t) noexcept ;
1608
1609    template<typename T>
1610    void __zngur_internal_assume_deinit(T& t) noexcept ;
1611
1612    template<typename T>
1613    inline size_t __zngur_internal_size_of() noexcept ;
1614
1615    template<typename T>
1616    inline void __zngur_internal_move_to_rust(uint8_t* dst, T& t) noexcept {
1617        memcpy(dst, ::rust::__zngur_internal_data_ptr(t), ::rust::__zngur_internal_size_of<T>());
1618        ::rust::__zngur_internal_assume_deinit(t);
1619    }
1620
1621    template<typename T>
1622    inline T __zngur_internal_move_from_rust(uint8_t* src) noexcept {
1623        T t;
1624        ::rust::__zngur_internal_assume_init(t);
1625        memcpy(::rust::__zngur_internal_data_ptr(t), src, ::rust::__zngur_internal_size_of<T>());
1626        return t;
1627    }
1628
1629    template<typename T>
1630    inline void __zngur_internal_check_init(const T&) noexcept {
1631    }
1632
1633    class ZngurCppOpaqueOwnedObject {
1634        uint8_t* data;
1635        void (*destructor)(uint8_t*);
1636
1637    public:
1638        template<typename T, typename... Args>
1639        inline static ZngurCppOpaqueOwnedObject build(Args&&... args) {
1640            ZngurCppOpaqueOwnedObject o;
1641            o.data = reinterpret_cast<uint8_t*>(new T(::std::forward<Args>(args)...));
1642            o.destructor = [](uint8_t* d) {
1643                delete reinterpret_cast<T*>(d);
1644            };
1645            return o;
1646        }
1647
1648        template<typename T>
1649        inline T& as_cpp() {
1650            return *reinterpret_cast<T *>(data);
1651        }
1652    };
1653
1654    template<typename T>
1655    struct Ref;
1656
1657    template<typename T>
1658    struct RefMut;
1659
1660    template<typename T, size_t OFFSET>
1661    struct FieldOwned {
1662        inline operator T() const noexcept { return *::rust::Ref<T>(*this); }
1663    };
1664
1665    template<typename T, size_t OFFSET>
1666    struct FieldRef {
1667        inline operator T() const noexcept { return *::rust::Ref<T>(*this); }
1668    };
1669
1670    template<typename T, size_t OFFSET>
1671    struct FieldRefMut {
1672        inline operator T() const noexcept { return *::rust::Ref<T>(*this); }
1673    };
1674
1675    template<typename... T>
1676    struct Tuple;
1677
1678    using Unit = Tuple<>;
1679
1680    template<typename T>
1681    struct ZngurPrettyPrinter;
1682
1683    class Inherent;
1684
1685    template<typename Type, typename Trait = Inherent>
1686    class Impl;
1687
1688    template<typename T>
1689    T&& zngur_dbg_impl(const char* file_name, int line_number, const char* exp, T&& input) {
1690        ::std::cerr << "[" << file_name << ":" << line_number << "] " << exp << " = ";
1691        ZngurPrettyPrinter<typename ::std::remove_reference<T>::type>::print(input);
1692        return ::std::forward<T>(input);
1693    }
1694"#;
1695        for ty in [8, 16, 32, 64]
1696            .into_iter()
1697            .flat_map(|x| [format!("int{x}_t"), format!("uint{x}_t")])
1698            .chain([8, 16, 32, 64].into_iter().flat_map(|x| {
1699                [
1700                    format!("::rust::Ref<int{x}_t>"),
1701                    format!("::rust::Ref<uint{x}_t>"),
1702                    format!("::rust::RefMut<int{x}_t>"),
1703                    format!("::rust::RefMut<uint{x}_t>"),
1704                ]
1705            }))
1706            .chain([
1707                "::rust::ZngurCppOpaqueOwnedObject".to_string(),
1708                "::double_t".to_string(),
1709                "::float_t".to_string(),
1710                "::size_t".to_string(),
1711            ])
1712        {
1713            let needs_endif = match ty.as_str() {
1714                "::size_t" => {
1715                    // Apple and WASM treat size_t as a distinct type, not a typedef'd primitive.
1716                    writeln!(state, "#if defined(__APPLE__) || defined(__wasm__)")?;
1717                    true
1718                }
1719                _ => false,
1720            };
1721            writeln!(
1722                state,
1723                r#"
1724    template<>
1725    inline uint8_t* __zngur_internal_data_ptr< {ty} >(const {ty}& t) noexcept {{
1726        return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&t));
1727    }}
1728
1729    template<>
1730    inline void __zngur_internal_assume_init< {ty} >({ty}&) noexcept {{}}
1731    template<>
1732    inline void __zngur_internal_assume_deinit< {ty} >({ty}&) noexcept {{}}
1733
1734    template<>
1735    inline size_t __zngur_internal_size_of< {ty} >() noexcept {{
1736        return sizeof({ty});
1737    }}
1738
1739    template<>
1740    inline uint8_t* __zngur_internal_data_ptr< {ty}*>({ty}* const & t) noexcept {{
1741        return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&t));
1742    }}
1743
1744    template<>
1745    inline void __zngur_internal_assume_init< {ty}*>({ty}*&) noexcept {{}}
1746    template<>
1747    inline void __zngur_internal_assume_deinit< {ty}*>({ty}*&) noexcept {{}}
1748
1749    template<>
1750    inline uint8_t* __zngur_internal_data_ptr< {ty} const*>({ty} const* const & t) noexcept {{
1751        return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&t));
1752    }}
1753
1754    template<>
1755    inline void __zngur_internal_assume_init< {ty} const*>({ty} const*&) noexcept {{}}
1756    template<>
1757    inline void __zngur_internal_assume_deinit< {ty} const*>({ty} const*&) noexcept {{}}
1758
1759    template<>
1760    struct Ref< {ty} > {{
1761        Ref() {{
1762            data = 0;
1763        }}
1764        Ref(const {ty}& t) {{
1765            data = reinterpret_cast<size_t>(__zngur_internal_data_ptr(t));
1766        }}
1767
1768         template<size_t OFFSET>
1769         Ref(const FieldOwned< {ty}, OFFSET >& f) {{
1770             data = reinterpret_cast<size_t>(&f) + OFFSET;
1771         }}
1772
1773         template<size_t OFFSET>
1774         Ref(const FieldRef< {ty}, OFFSET >& f) {{
1775             data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
1776         }}
1777
1778         template<size_t OFFSET>
1779         Ref(const FieldRefMut< {ty}, OFFSET >& f) {{
1780             data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
1781         }}
1782
1783        {ty}& operator*() {{
1784            return *reinterpret_cast< {ty}*>(data);
1785        }}
1786        private:
1787            size_t data;
1788        friend uint8_t* ::rust::__zngur_internal_data_ptr<Ref< {ty} > >(const ::rust::Ref< {ty} >& t) noexcept ;
1789        friend ::rust::ZngurPrettyPrinter< Ref< {ty} > >;
1790    }};
1791
1792    template<>
1793    struct RefMut< {ty} > {{
1794        RefMut() {{
1795            data = 0;
1796        }}
1797        RefMut({ty}& t) {{
1798            data = reinterpret_cast<size_t>(__zngur_internal_data_ptr(t));
1799        }}
1800
1801         template<size_t OFFSET>
1802         RefMut(const FieldOwned< {ty}, OFFSET >& f) {{
1803             data = reinterpret_cast<size_t>(&f) + OFFSET;
1804         }}
1805
1806         template<size_t OFFSET>
1807         RefMut(const FieldRefMut< {ty}, OFFSET >& f) {{
1808             data = *reinterpret_cast<const size_t*>(&f) + OFFSET;
1809         }}
1810
1811        {ty}& operator*() {{
1812            return *reinterpret_cast< {ty}*>(data);
1813        }}
1814        private:
1815            size_t data;
1816        friend uint8_t* ::rust::__zngur_internal_data_ptr<RefMut< {ty} > >(const ::rust::RefMut< {ty} >& t) noexcept ;
1817        friend ::rust::ZngurPrettyPrinter< Ref< {ty} > >;
1818    }};
1819"#
1820            )?;
1821            if ty.starts_with("int")
1822                || ty.starts_with("uint")
1823                || ty.starts_with("::size_t")
1824                || ty.starts_with("::double")
1825                || ty.starts_with("::float")
1826            {
1827                writeln!(
1828                    state,
1829                    r#"
1830    template<>
1831    struct ZngurPrettyPrinter<{ty}> {{
1832        static inline void print({ty} const& t) {{
1833            ::std::cerr << t << ::std::endl;
1834        }}
1835    }};
1836                    "#
1837                )?;
1838            }
1839
1840            if needs_endif {
1841                writeln!(state, "#endif")?;
1842            }
1843        }
1844        writeln!(state, "}}")?;
1845        writeln!(state, "extern \"C\" {{")?;
1846        for f in &self.fn_defs {
1847            f.sig.emit_rust_link_decl(state)?;
1848        }
1849        for td in &self.type_defs {
1850            td.emit_rust_links(state)?;
1851        }
1852        for (_, td) in &self.trait_defs {
1853            td.emit_rust_links(state)?;
1854        }
1855        writeln!(state, "}}")?;
1856        for td in &self.type_defs {
1857            td.ty.emit_header(state)?;
1858        }
1859        for imp in &self.exported_impls {
1860            imp.ty.emit_header(state)?;
1861            if let Some(tr) = &imp.tr {
1862                tr.emit_header(state)?;
1863            }
1864        }
1865        for (_, td) in &self.trait_defs {
1866            td.emit(state)?;
1867        }
1868        for td in &self.type_defs {
1869            td.emit(state)?;
1870        }
1871        for td in &self.type_defs {
1872            td.emit_cpp_fn_defs(state, &self.trait_defs)?;
1873        }
1874        for fd in &self.fn_defs {
1875            fd.emit_cpp_def(state)?;
1876        }
1877        for func in &self.exported_fn_defs {
1878            writeln!(state, "namespace rust {{ namespace exported_functions {{")?;
1879            write!(state, "   {} {}(", func.sig.output, func.name)?;
1880            for (n, ty) in func.sig.inputs.iter().enumerate() {
1881                if n != 0 {
1882                    write!(state, ", ")?;
1883                }
1884                write!(state, "{ty} i{n}")?;
1885            }
1886            writeln!(state, ");")?;
1887            writeln!(state, "}} }}")?;
1888        }
1889        for imp in &self.exported_impls {
1890            writeln!(
1891                state,
1892                "namespace rust {{ template<> class Impl< {}, {} > {{ public:",
1893                imp.ty,
1894                match &imp.tr {
1895                    Some(x) => format!("{x}"),
1896                    None => "::rust::Inherent".to_string(),
1897                }
1898            )?;
1899            for (name, sig) in &imp.methods {
1900                write!(state, "   static {} {}(", sig.output, name)?;
1901                for (n, ty) in sig.inputs.iter().enumerate() {
1902                    if n != 0 {
1903                        write!(state, ", ")?;
1904                    }
1905                    write!(state, "{ty} i{n}")?;
1906                }
1907                writeln!(state, ");")?;
1908            }
1909            writeln!(state, "}}; }}")?;
1910        }
1911        Ok(())
1912    }
1913
1914    fn emit_cpp_file(&self, state: &mut State, is_really_needed: &mut bool) -> std::fmt::Result {
1915        writeln!(state, r#"#include "./generated.h""#)?;
1916        writeln!(state, "extern \"C\" {{")?;
1917        for t in &self.trait_defs {
1918            *is_really_needed = true;
1919            t.1.emit_cpp(state)?;
1920        }
1921        for func in &self.exported_fn_defs {
1922            *is_really_needed = true;
1923            func.sig.emit_rust_link(state)?;
1924            writeln!(state, "{{")?;
1925            writeln!(
1926                state,
1927                "   {} oo = ::rust::exported_functions::{}({});",
1928                func.sig.output,
1929                func.name,
1930                func.sig
1931                    .inputs
1932                    .iter()
1933                    .enumerate()
1934                    .map(|(n, ty)| {
1935                        format!("::rust::__zngur_internal_move_from_rust< {ty} >(i{n})")
1936                    })
1937                    .join(", "),
1938            )?;
1939            writeln!(state, "   ::rust::__zngur_internal_move_to_rust(o, oo);")?;
1940            writeln!(state, "}}")?;
1941        }
1942        for imp in &self.exported_impls {
1943            *is_really_needed = true;
1944            for (name, sig) in &imp.methods {
1945                sig.emit_rust_link(state)?;
1946                writeln!(state, "{{")?;
1947                writeln!(
1948                    state,
1949                    "   {} oo = ::rust::Impl< {}, {} >::{}({});",
1950                    sig.output,
1951                    imp.ty,
1952                    match &imp.tr {
1953                        Some(x) => format!("{x}"),
1954                        None => "::rust::Inherent".to_string(),
1955                    },
1956                    name,
1957                    sig.inputs
1958                        .iter()
1959                        .enumerate()
1960                        .map(|(n, ty)| {
1961                            format!("::rust::__zngur_internal_move_from_rust< {ty} >(i{n})")
1962                        })
1963                        .join(", "),
1964                )?;
1965                writeln!(state, "   ::rust::__zngur_internal_move_to_rust(o, oo);")?;
1966                writeln!(state, "}}")?;
1967            }
1968        }
1969        writeln!(state, "}}")?;
1970        Ok(())
1971    }
1972
1973    pub fn render(self) -> (String, Option<String>) {
1974        let mut h_file = State {
1975            text: "".to_owned(),
1976            panic_to_exception: self.panic_to_exception,
1977        };
1978        let mut cpp_file = State {
1979            text: "".to_owned(),
1980            panic_to_exception: self.panic_to_exception,
1981        };
1982        self.emit_h_file(&mut h_file).unwrap();
1983        let mut is_cpp_needed = false;
1984        self.emit_cpp_file(&mut cpp_file, &mut is_cpp_needed)
1985            .unwrap();
1986        h_file.remove_no_except_in_panic();
1987        (h_file.text, is_cpp_needed.then_some(cpp_file.text))
1988    }
1989}
1990
1991pub fn cpp_handle_keyword(name: &str) -> &str {
1992    match name {
1993        "new" => "new_",
1994        "default" => "default_",
1995        x => x,
1996    }
1997}
1998
1999pub fn cpp_handle_field_name(name: &str) -> String {
2000    if name.parse::<u32>().is_ok() {
2001        return format!("f{name}");
2002    }
2003    cpp_handle_keyword(name).to_owned()
2004}