Skip to main content

zngur_def/
lib.rs

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