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}