zngur_def/
lib.rs

1use std::{collections::HashMap, fmt::Display};
2
3use itertools::Itertools;
4
5mod merge;
6pub use merge::{Merge, MergeFailure, MergeResult};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum Mutability {
10    Mut,
11    Not,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum ZngurMethodReceiver {
16    Static,
17    Ref(Mutability),
18    Move,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Hash)]
22pub struct ZngurMethod {
23    pub name: String,
24    pub generics: Vec<RustType>,
25    pub receiver: ZngurMethodReceiver,
26    pub inputs: Vec<RustType>,
27    pub output: RustType,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq, Hash)]
31pub struct ZngurFn {
32    pub path: RustPathAndGenerics,
33    pub inputs: Vec<RustType>,
34    pub output: RustType,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Hash)]
38pub struct ZngurExternCppFn {
39    pub name: String,
40    pub inputs: Vec<RustType>,
41    pub output: RustType,
42}
43
44#[derive(Debug, Clone, PartialEq, Eq, Hash)]
45pub struct ZngurExternCppImpl {
46    pub tr: Option<RustTrait>,
47    pub ty: RustType,
48    pub methods: Vec<ZngurMethod>,
49}
50
51#[derive(Debug, PartialEq, Eq)]
52pub struct ZngurConstructor {
53    pub name: Option<String>,
54    pub inputs: Vec<(String, RustType)>,
55}
56
57#[derive(Debug, PartialEq, Eq)]
58pub struct ZngurField {
59    pub name: String,
60    pub ty: RustType,
61    pub offset: usize,
62}
63
64#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
65pub enum ZngurWellknownTrait {
66    Debug,
67    Drop,
68    Unsized,
69    Copy,
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Hash)]
73pub enum ZngurWellknownTraitData {
74    Debug {
75        pretty_print: String,
76        debug_print: String,
77    },
78    Drop {
79        drop_in_place: String,
80    },
81    Unsized,
82    Copy,
83}
84
85#[derive(Debug, Clone, Copy, PartialEq, Eq)]
86pub enum LayoutPolicy {
87    StackAllocated { size: usize, align: usize },
88    HeapAllocated,
89    OnlyByRef,
90}
91
92impl LayoutPolicy {
93    pub const ZERO_SIZED_TYPE: Self = LayoutPolicy::StackAllocated { size: 0, align: 1 };
94}
95
96#[derive(Debug, PartialEq, Eq)]
97pub struct ZngurMethodDetails {
98    pub data: ZngurMethod,
99    pub use_path: Option<Vec<String>>,
100    pub deref: Option<RustType>,
101}
102
103#[derive(Debug, PartialEq, Eq)]
104pub struct CppValue(pub String, pub String);
105
106#[derive(Debug, PartialEq, Eq)]
107pub struct CppRef(pub String);
108
109impl Display for CppRef {
110    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
111        write!(f, "{}", self.0)
112    }
113}
114
115#[derive(Debug)]
116pub struct ZngurType {
117    pub ty: RustType,
118    pub layout: LayoutPolicy,
119    pub wellknown_traits: Vec<ZngurWellknownTrait>,
120    pub methods: Vec<ZngurMethodDetails>,
121    pub constructors: Vec<ZngurConstructor>,
122    pub fields: Vec<ZngurField>,
123    pub cpp_value: Option<CppValue>,
124    pub cpp_ref: Option<CppRef>,
125}
126
127#[derive(Debug)]
128pub struct ZngurTrait {
129    pub tr: RustTrait,
130    pub methods: Vec<ZngurMethod>,
131}
132
133#[derive(Debug, Default)]
134pub struct AdditionalIncludes(pub String);
135
136#[derive(Debug, Default)]
137pub struct ConvertPanicToException(pub bool);
138
139#[derive(Clone, Debug, Default)]
140pub struct Import(pub std::path::PathBuf);
141#[derive(Debug, Default)]
142pub struct ZngurSpec {
143    pub imports: Vec<Import>,
144    pub types: Vec<ZngurType>,
145    pub traits: HashMap<RustTrait, ZngurTrait>,
146    pub funcs: Vec<ZngurFn>,
147    pub extern_cpp_funcs: Vec<ZngurExternCppFn>,
148    pub extern_cpp_impls: Vec<ZngurExternCppImpl>,
149    pub additional_includes: AdditionalIncludes,
150    pub convert_panic_to_exception: ConvertPanicToException,
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Hash)]
154pub enum RustTrait {
155    Normal(RustPathAndGenerics),
156    Fn {
157        name: String,
158        inputs: Vec<RustType>,
159        output: Box<RustType>,
160    },
161}
162
163impl RustTrait {
164    pub fn take_assocs(mut self) -> (Self, Vec<(String, RustType)>) {
165        let assocs = match &mut self {
166            RustTrait::Normal(p) => std::mem::take(&mut p.named_generics),
167            RustTrait::Fn { .. } => vec![],
168        };
169        (self, assocs)
170    }
171}
172
173#[derive(Debug, Clone, PartialEq, Eq, Hash)]
174pub enum PrimitiveRustType {
175    Uint(u32),
176    Int(u32),
177    Float(u32),
178    Usize,
179    Bool,
180    Str,
181    ZngurCppOpaqueOwnedObject,
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, Hash)]
185pub struct RustPathAndGenerics {
186    pub path: Vec<String>,
187    pub generics: Vec<RustType>,
188    pub named_generics: Vec<(String, RustType)>,
189}
190
191#[derive(Debug, Clone, PartialEq, Eq, Hash)]
192pub enum RustType {
193    Primitive(PrimitiveRustType),
194    Ref(Mutability, Box<RustType>),
195    Raw(Mutability, Box<RustType>),
196    Boxed(Box<RustType>),
197    Slice(Box<RustType>),
198    Dyn(RustTrait, Vec<String>),
199    Tuple(Vec<RustType>),
200    Adt(RustPathAndGenerics),
201}
202
203impl RustType {
204    pub const UNIT: Self = RustType::Tuple(Vec::new());
205}
206
207impl Display for RustPathAndGenerics {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        let RustPathAndGenerics {
210            path,
211            generics,
212            named_generics,
213        } = self;
214        for p in path {
215            if p != "crate" {
216                write!(f, "::")?;
217            }
218            write!(f, "{p}")?;
219        }
220        if !generics.is_empty() || !named_generics.is_empty() {
221            write!(
222                f,
223                "::<{}>",
224                generics
225                    .iter()
226                    .map(|x| format!("{x}"))
227                    .chain(named_generics.iter().map(|x| format!("{} = {}", x.0, x.1)))
228                    .join(", ")
229            )?;
230        }
231        Ok(())
232    }
233}
234
235impl Display for RustTrait {
236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237        match self {
238            RustTrait::Normal(tr) => write!(f, "{tr}"),
239            RustTrait::Fn {
240                name,
241                inputs,
242                output,
243            } => {
244                write!(f, "{name}({})", inputs.iter().join(", "))?;
245                if **output != RustType::UNIT {
246                    write!(f, " -> {output}")?;
247                }
248                Ok(())
249            }
250        }
251    }
252}
253
254impl Display for RustType {
255    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
256        match self {
257            RustType::Primitive(s) => match s {
258                PrimitiveRustType::Uint(s) => write!(f, "u{s}"),
259                PrimitiveRustType::Int(s) => write!(f, "i{s}"),
260                PrimitiveRustType::Float(s) => write!(f, "f{s}"),
261                PrimitiveRustType::Usize => write!(f, "usize"),
262                PrimitiveRustType::Bool => write!(f, "bool"),
263                PrimitiveRustType::Str => write!(f, "str"),
264                PrimitiveRustType::ZngurCppOpaqueOwnedObject => {
265                    write!(f, "ZngurCppOpaqueOwnedObject")
266                }
267            },
268            RustType::Ref(Mutability::Not, ty) => write!(f, "&{ty}"),
269            RustType::Ref(Mutability::Mut, ty) => write!(f, "&mut {ty}"),
270            RustType::Raw(Mutability::Not, ty) => write!(f, "*const {ty}"),
271            RustType::Raw(Mutability::Mut, ty) => write!(f, "*mut {ty}"),
272            RustType::Boxed(ty) => write!(f, "Box<{ty}>"),
273            RustType::Tuple(v) => write!(f, "({})", v.iter().join(", ")),
274            RustType::Adt(pg) => write!(f, "{pg}"),
275            RustType::Dyn(tr, marker_bounds) => {
276                write!(f, "dyn {tr}")?;
277                for mb in marker_bounds {
278                    write!(f, "+ {mb}")?;
279                }
280                Ok(())
281            }
282            RustType::Slice(s) => write!(f, "[{s}]"),
283        }
284    }
285}