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}