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