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}