1use std::fmt::Display;
19
20use crate::extern_module_translator::{
21 ExternModuleTranslator,
22 Function,
23 RustWrapperType,
24 WrapperType,
25};
26use crate::{DROP_FUNCTION_SYMBOL_NAME, EXPORTED_SYMBOLS_PREFIX};
27
28pub const RUST_EXCEPTION_BASE_CLASS_NAME: &str = "RustExceptionBase";
29pub const IMPORTS: &str = r#"
30#include <string>
31#include <cstring>
32#include <memory>
33#include <utility>
34#include <stdexcept>
35#include <cstdint>
36"#;
37
38pub const TYPEDEFS: &str = r#"
39using u8 = unsigned char;
40using u16 = unsigned short;
41using u32 = unsigned int;
42using u64 = unsigned long long;
43
44using i8 = char;
45using i16 = short;
46using i32 = int;
47using i64 = long long;
48
49using f32 = float;
50using f64 = double;
51
52using isize = int;
53using usize = unsigned int;
54"#;
55
56pub trait TargetLanguageTypeName {
57 fn get_name(&self) -> String;
58 fn get_name_for_abstract_method(&self) -> String;
59}
60
61impl TargetLanguageTypeName for WrapperType {
62 fn get_name(&self) -> String {
63 match self {
64 WrapperType {
65 rust_type: RustWrapperType::Vector(inner_type),
66 ..
67 } => {
68 let inner_name = inner_type.get_name();
69 format!("RustVec<{inner_name}>")
70 }
71 WrapperType {
72 rust_type: RustWrapperType::Option(inner_type),
73 ..
74 } => {
75 let inner_name = inner_type.get_name();
76 format!("Optional<{inner_name}>")
77 }
78 WrapperType {
79 rust_type: RustWrapperType::Result(ok_type, _),
80 ..
81 } => ok_type.get_name(),
82 _ => self.wrapper_name.clone(),
83 }
84 }
85 fn get_name_for_abstract_method(&self) -> String {
86 match self {
87 WrapperType {
88 rust_type: RustWrapperType::Vector(inner_type),
89 ..
90 } => {
91 let inner_name = inner_type.get_name();
92 format!("RustVec<{inner_name}>")
93 }
94 WrapperType {
95 rust_type: RustWrapperType::Option(inner_type),
96 ..
97 } => {
98 let inner_name = inner_type.get_name();
99 format!("Optional<{inner_name}>")
100 }
101 _ => self.wrapper_name.clone(),
102 }
103 }
104}
105
106pub const PREDEFINED: &str = const_format::formatcp!(
115 r#"
116extern "C" {{
117 void {DROP_FUNCTION_SYMBOL_NAME}(void* input) {{
118 }}
119}}
120
121template <typename T>
122class Optional {{
123 void* self = nullptr;
124 bool is_owned = false;
125public:
126 Optional();
127 Optional(T val);
128 Optional(void* self, bool is_owned = true) : self(self), is_owned(is_owned) {{}}
129 Optional(Optional&& a) : self(a.self), is_owned(a.is_owned) {{ a.self = nullptr; a.is_owned = false; }};
130 Optional(const Optional& a);
131 Optional& operator=(const Optional& a);
132 virtual ~Optional();
133 T unwrap();
134 bool is_some();
135 operator void*() {{
136 this->is_owned = false;
137 return this->self;
138 }}
139 void* as_ref() const {{
140 return this->self;
141 }}
142}};
143
144template <typename T>
145class RustVec;
146
147// RustIterator is separated from the RustVec class because SWIG does not fully support nested classes.
148template <typename T>
149struct RustIterator {{
150 RustIterator(T* buf_ptr, size_t index, bool is_primitive, RustVec<T>* vec)
151 : buf_ptr(buf_ptr), is_primitive(is_primitive), index(index), vec(vec)
152 {{}}
153
154 T operator*() const {{
155 return deref();
156 }}
157 T operator->() {{
158 return deref();
159 }}
160
161 RustIterator& operator++() {{
162 index++; return *this;
163 }}
164 RustIterator operator++(int) {{
165 RustIterator tmp = *this; ++(*this); return tmp;
166 }}
167 RustIterator operator+(int advance) {{
168 return RustIterator(buf_ptr, index + advance, is_primitive, vec);
169 }}
170
171 RustIterator& operator--() {{
172 index--; return *this;
173 }}
174 RustIterator operator--(int) {{
175 RustIterator tmp = *this; --(*this); return tmp;
176 }}
177 RustIterator operator-(int advance) {{
178 return RustIterator(buf_ptr, index - advance, is_primitive, vec);
179 }}
180
181 friend bool operator== (const RustIterator& a, const RustIterator& b) {{ return a.buf_ptr == b.buf_ptr && a.index == b.index ; }};
182 friend bool operator!= (const RustIterator& a, const RustIterator& b) {{ return a.buf_ptr != b.buf_ptr || a.index != b.index ; }};
183
184private:
185 T deref() const {{
186 if (is_primitive) {{
187 return *(buf_ptr + index);
188 }} else {{
189 return vec->at(index).unwrap();
190 }}
191 }}
192
193 RustVec<T>* vec;
194 T* buf_ptr;
195 bool is_primitive;
196 size_t index;
197}};
198
199template <typename T>
200class RustVec {{
201 void* self = nullptr;
202 bool is_owned = false;
203
204 T* as_mut_ptr();
205
206public:
207 RustVec();
208 RustVec(RustVec&& a) : self(a.self), is_owned(a.is_owned) {{
209 a.self = nullptr;
210 a.is_owned = false;
211 }};
212 RustVec(const RustVec&);
213 RustVec& operator=(const RustVec&);
214 RustVec(void* self, bool is_owned = true)
215 : self(self), is_owned(is_owned) {{}}
216 virtual ~RustVec();
217 operator void*() {{
218 this->is_owned = false;
219 return this->self;
220 }}
221 void* as_ref() const {{
222 return this->self;
223 }}
224 void push(T item);
225 Optional<T> at(usize index);
226 size_t size();
227
228 RustIterator<T> begin();
229 RustIterator<T> end();
230}};
231
232class RustString {{
233 void* self = nullptr;
234 bool is_owned = false;
235public:
236 RustString() = default;
237 RustString(void* self, bool is_owned = true)
238 : self(self), is_owned(is_owned) {{}}
239 RustString(const char* str) {{
240 this->self = {EXPORTED_SYMBOLS_PREFIX}$RustString$from_c_str((void*) str);
241 this->is_owned = true;
242 }}
243 RustString(std::string str) {{
244 this->self = {EXPORTED_SYMBOLS_PREFIX}$RustString$from_c_str((void*) str.data());
245 this->is_owned = true;
246 }}
247 RustString(const RustString& a) {{
248 this->self = {EXPORTED_SYMBOLS_PREFIX}$RustString$clone(a.self);
249 this->is_owned = true;
250 }}
251 RustString(RustString&& a)
252 : self(a.self),
253 is_owned(a.is_owned) {{
254 a.self = nullptr;
255 a.is_owned = false;
256 }}
257 RustString& operator=(const RustString& a) {{
258 this->self = {EXPORTED_SYMBOLS_PREFIX}$RustString$clone(a.self);
259 this->is_owned = true;
260 return *this;
261 }};
262 RustString& operator=(RustString&& a) {{
263 this->is_owned = true;
264 a.is_owned = false;
265 this->self = a.self;
266 a.self = nullptr;
267 return *this;
268 }}
269 std::string to_string() {{
270 char* str = (char*) {EXPORTED_SYMBOLS_PREFIX}$RustString$as_mut_ptr(this->self);
271 usize length = {EXPORTED_SYMBOLS_PREFIX}$RustString$len(this->self);
272 return std::string(str, length);
273 }}
274 operator void*() {{
275 this->is_owned = false;
276 return this->self;
277 }}
278 void* as_ref() const {{
279 return this->self;
280 }}
281 virtual ~RustString() {{
282 if(is_owned && self != nullptr) {{
283 {EXPORTED_SYMBOLS_PREFIX}$RustString$drop(this->self);
284 }}
285 }}
286}};
287
288using String = RustString;
289"#
290);
291
292pub fn begin_end_impl(inner_type: &str, rust_type: &RustWrapperType) -> String {
296 let is_primitive = if matches!(rust_type, RustWrapperType::Primitive) {
297 "true"
298 } else {
299 "false"
300 };
301 format!(
302 "
303template<>
304RustIterator<{inner_type}> RustVec<{inner_type}>::begin() {{
305 return RustIterator( as_mut_ptr(), 0, {is_primitive}, this );
306}}
307template<>
308RustIterator<{inner_type}> RustVec<{inner_type}>::end() {{
309 return RustIterator( as_mut_ptr(), size(), {is_primitive}, this );
310}}
311"
312 )
313}
314
315pub fn vector_impl(inner_type: &str, rust_wrapper_name: &str) -> String {
318 format!(
319 "
320template<>
321RustVec<{inner_type}>::~RustVec()
322{{
323 if(this->self && this->is_owned) {{
324 {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$drop(this->self);
325 }}
326}}
327
328template<>
329void RustVec<{inner_type}>::push({inner_type} item) {{
330 {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$push(this->self, item);
331}}
332template<>
333RustVec<{inner_type}>::RustVec(const RustVec& vec) {{
334 this->self = {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$clone(vec.self);
335 this->is_owned = true;
336}}
337template<>
338RustVec<{inner_type}>& RustVec<{inner_type}>::operator=(const RustVec& vec) {{
339 this->self = {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$clone(vec.self);
340 this->is_owned = true;
341 return *this;
342}}
343template<>
344RustVec<{inner_type}>::RustVec() {{
345 this->self = {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$new();
346 this->is_owned = true;
347}}
348template<>
349Optional<{inner_type}> RustVec<{inner_type}>::at(usize index) {{
350 return Optional<{inner_type}>({EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$get(this->self, index));
351}}
352template<>
353{inner_type}* RustVec<{inner_type}>::as_mut_ptr() {{
354 return ({inner_type}*) {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$as_mut_ptr(this->self);
355}}
356template<>
357size_t RustVec<{inner_type}>::size() {{
358 return (size_t) {EXPORTED_SYMBOLS_PREFIX}$Vec{rust_wrapper_name}$len(this->self);
359}}"
360 )
361}
362
363pub fn option_class(inner_type: &str, rust_wrapper_name: &str) -> String {
367 format!(
368 "
369template<>
370Optional<{inner_type}>::Optional() {{
371 this->self = {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$default();
372 this->is_owned = true;
373}}
374template<>
375Optional<{inner_type}>::Optional({inner_type} val) {{
376 this->self = {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$from(val);
377 this->is_owned = true;
378}}
379template<>
380Optional<{inner_type}>::Optional(const Optional<{inner_type}>& a) {{
381 this->self = {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$clone(a.self);
382 this->is_owned = true;
383}}
384template<>
385Optional<{inner_type}>& Optional<{inner_type}>::operator=(const Optional<{inner_type}>& a) {{
386 this->self = {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$clone(a.self);
387 this->is_owned = true;
388 return *this;
389}}
390template<>
391Optional<{inner_type}>::~Optional() {{
392 if(this->self && this->is_owned) {{
393 {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$drop(this->self);
394 }}
395}};
396template<>
397{inner_type} Optional<{inner_type}>::unwrap() {{
398 auto cloned = {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$clone(this->self);
399 return {inner_type}({EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$unwrap(cloned));
400}}
401template<>
402bool Optional<{inner_type}>::is_some() {{
403 return {EXPORTED_SYMBOLS_PREFIX}$Optional{rust_wrapper_name}$is_some(this->self);
404}}
405"
406 )
407}
408
409pub fn result_class(name: &str, ok_type: &str, err_type: &str) -> String {
413 format!(
414 "
415class {name} {{
416 void* self = nullptr;
417 bool is_owned = false;
418public:
419 {name}() = default;
420 {name}({name}&& a) : self(a.self), is_owned(a.is_owned) {{
421 a.self = nullptr;
422 a.is_owned = false;
423 }};
424 {name}(const {name}& a) {{
425 this->self = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(a.self);
426 this->is_owned = true;
427 }}
428 {name}& operator=(const {name}& a) {{
429 this->self = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(a.self);
430 this->is_owned = true;
431 return *this;
432 }}
433 {name}(void* self, bool is_owned = true) : self(self), is_owned(is_owned) {{ }}
434 virtual ~{name}() {{
435 if(this->self && this->is_owned) {{
436 {EXPORTED_SYMBOLS_PREFIX}${name}$drop(this->self);
437 }}
438 }}
439 static {name} from_ok({ok_type} val) {{
440 return {name}({EXPORTED_SYMBOLS_PREFIX}${name}$from_ok(val));
441 }}
442 static {name} from_err({err_type} val) {{
443 return {name}({EXPORTED_SYMBOLS_PREFIX}${name}$from_err(val));
444 }}
445 {ok_type} unwrap() {{
446 auto cloned = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(this->self);
447 return {ok_type}({EXPORTED_SYMBOLS_PREFIX}${name}$unwrap(cloned));
448 }}
449 {err_type} unwrap_err() {{
450 auto cloned = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(this->self);
451 return {err_type}({EXPORTED_SYMBOLS_PREFIX}${name}$unwrap_err_unchecked(cloned));
452 }}
453 bool is_ok() {{
454 return {EXPORTED_SYMBOLS_PREFIX}${name}$is_ok(this->self);
455 }}
456 operator void*() {{
457 this->is_owned = false;
458 return this->self;
459 }}
460 void* as_ref() const {{
461 return this->self;
462 }}
463}};
464"
465 )
466}
467
468pub fn custom_class_definition(name: impl Display, functions_declaration: impl Display) -> String {
473 format!(
474 "
475class {name} {{
476 void* self = nullptr;
477 bool is_owned = false;
478public:
479 {name}() = default;
480 {name}(void* self, bool is_owned = true) : self(self), is_owned(is_owned) {{ }}
481 {name}({name}&& a) : self(a.self), is_owned(a.is_owned) {{ a.self = nullptr; a.is_owned = false; }};
482 {name}(const {name}& a) {{
483 this->self = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(a.self);
484 this->is_owned = true;
485 }}
486 {name}& operator=(const {name}& a) {{
487 this->self = {EXPORTED_SYMBOLS_PREFIX}${name}$clone(a.self);
488 this->is_owned = true;
489 return *this;
490 }}
491 {name}& operator=({name}&& a) {{
492 this->is_owned = true;
493 a.is_owned = false;
494 this->self = a.self;
495 a.self = nullptr;
496 return *this;
497 }}
498 virtual ~{name}() {{ if(this->self && this->is_owned) {{ {EXPORTED_SYMBOLS_PREFIX}${name}$drop(this->self); }} }};
499 operator void*() {{
500 this->is_owned = false;
501 return this->self;
502 }}
503 void* raw_self() const {{ return this->self;}}
504 void* as_ref() const {{
505 return this->self;
506 }}
507{functions_declaration}
508}};
509\n")
510}
511
512pub fn abstract_class_declaration(name: &str, functions_declaration: &str) -> String {
517 format!(
518 "
519class {name} {{
520public:
521 {name}() = default;
522 virtual ~{name}() {{}};
523 operator void*() const {{
524 return (void*) this;
525 }}
526{functions_declaration}}};
527\n"
528 )
529}
530
531pub fn create_non_primitive_exception_class<'a>(
533 exception: &impl Display,
534 err_name: &impl Display,
535 custom_methods: impl Iterator<Item = &'a Function>,
536) -> String {
537 let custom_methods =
538 create_non_primitive_enum_exception_custom_methods(custom_methods, err_name);
539 format_exception_class(exception, err_name, &custom_methods)
540}
541
542pub fn create_primitive_exception_class<'a>(
544 exception: &impl Display,
545 err_name: &impl Display,
546 custom_methods: impl Iterator<Item = &'a Function>,
547) -> String {
548 let custom_methods = create_primitive_enum_exception_custom_methods(custom_methods, err_name);
549 format_exception_class(exception, err_name, &custom_methods)
550}
551
552pub fn exception_class_name(
553 error_enum_name: impl Display,
554 exception_variant: impl Display,
555) -> String {
556 format!("{error_enum_name}_{exception_variant}Exception")
557}
558
559fn format_exception_class(
560 exception: &impl Display,
561 err_name: &impl Display,
562 custom_methods: &impl Display,
563) -> String {
564 let exception_name = exception_class_name(err_name, exception);
565 format!(
566 "
567class {exception_name} : public {RUST_EXCEPTION_BASE_CLASS_NAME} {{
568 {err_name} err;
569 public:
570 {exception_name}({err_name} err) : err{{err}} {{}}
571
572 virtual const char* what() const throw() override
573 {{
574 return \"{exception_name} thrown from Rust\";
575 }}
576
577 virtual ExceptionClass exception_class() override {{
578 return ExceptionClass::{exception_name};
579 }}
580
581{custom_methods}
582 }};
583"
584 )
585}
586
587fn create_exception_custom_methods<'a>(
588 custom_methods: impl Iterator<Item = &'a Function>,
589 err_name: &impl Display,
590 inner_err_cast: &(impl Display + ?Sized),
591) -> impl Display {
592 custom_methods
593 .map(|fun| {
594 let return_type = fun
595 .return_type
596 .as_ref()
597 .map(|wrapper| wrapper.wrapper_name.as_str())
598 .unwrap_or("");
599 let function_name = &fun.name;
600 let ffi_call = format!("{EXPORTED_SYMBOLS_PREFIX}${err_name}${function_name}");
601 let ffi_call = format!("{ffi_call}({inner_err_cast})");
602 let ffi_call = match &fun.return_type {
603 None
604 | Some(WrapperType {
605 rust_type: RustWrapperType::Primitive | RustWrapperType::FieldlessEnum,
606 ..
607 }) => ffi_call,
608 Some(WrapperType { wrapper_name, .. }) => {
609 format!("{wrapper_name}({ffi_call})")
610 }
611 };
612 format!(
613 " {return_type} {function_name}() const override {{
614 return {ffi_call};
615 }}"
616 )
617 })
618 .collect::<Vec<_>>()
619 .join("\n")
620}
621
622fn create_primitive_enum_exception_custom_methods<'a>(
623 custom_methods: impl Iterator<Item = &'a Function>,
624 err_name: &impl Display,
625) -> impl Display {
626 create_exception_custom_methods(custom_methods, err_name, "(void*)&err")
627}
628
629fn create_non_primitive_enum_exception_custom_methods<'a>(
630 custom_methods: impl Iterator<Item = &'a Function>,
631 err_name: &impl Display,
632) -> impl Display {
633 create_exception_custom_methods(custom_methods, err_name, "err.raw_self()")
634}
635
636fn base_exception_virtual_method(function: &Function) -> String {
637 let return_type = &function
638 .return_type
639 .as_ref()
640 .map(|t| t.get_name())
641 .unwrap_or_else(|| "".to_string());
642 let name = &function.name;
643 format!(
644 " virtual {return_type} {name}() const = 0;
645"
646 )
647}
648
649fn wasm_delegated_exception_method(function: &Function) -> String {
650 let return_type = &function
651 .return_type
652 .as_ref()
653 .map(|t| t.get_name())
654 .unwrap_or_else(|| "".to_string());
655 let fun_name = &function.name;
656 format!(
657 " virtual {return_type} {fun_name}() const {{
658 return rbe->{fun_name}();
659 }};
660"
661 )
662}
663
664pub fn base_exception_class(emt: &ExternModuleTranslator) -> String {
665 let exception_trait_virtual_methods = emt
666 .exception_trait_methods
667 .iter()
668 .map(base_exception_virtual_method)
669 .collect::<Vec<_>>()
670 .join("\n");
671 let wasm_delegated_methods = emt
672 .exception_trait_methods
673 .iter()
674 .map(wasm_delegated_exception_method)
675 .collect::<Vec<_>>()
676 .join("\n");
677 format!(
678 "class {RUST_EXCEPTION_BASE_CLASS_NAME} : public std::exception {{
679public:
680 virtual const char* what() const throw()
681 {{
682 return \"Exception thrown from Rust\";
683 }}
684
685 virtual ExceptionClass exception_class() {{
686 return ExceptionClass::{RUST_EXCEPTION_BASE_CLASS_NAME};
687 }}
688
689{exception_trait_virtual_methods}
690}};
691
692// Exceptions wrapper for WASM
693class WasmException {{
694 std::shared_ptr<{RUST_EXCEPTION_BASE_CLASS_NAME}> rbe;
695public:
696 WasmException(unsigned addr) : rbe{{({RUST_EXCEPTION_BASE_CLASS_NAME}*) addr}} {{}}
697
698 ExceptionClass exception_class() {{
699 return rbe->exception_class();
700 }}
701
702 std::string what() {{
703 return std::string{{rbe->what()}};
704 }}
705
706{wasm_delegated_methods}
707}};
708"
709 )
710}