1use proc_macro_crate::{FoundCrate, crate_name};
2use proc_macro2::{Span, TokenStream};
3use quote::{format_ident, quote};
4use syn::parse::{Parse, ParseStream};
5use syn::spanned::Spanned;
6use syn::token::Brace;
7use syn::{
8 AngleBracketedGenericArguments, AttrStyle, CapturedParam, Error, GenericArgument, GenericParam,
9 Lifetime, LifetimeParam, MacroDelimiter, Meta, Path, PathArguments, ReturnType, Signature,
10 Token, TypeParamBound, parse2,
11};
12use syn::{
13 Attribute, Field, FnArg, Ident, ImplItemFn, Pat, Type, Visibility, braced, parse_macro_input,
14 parse_quote,
15};
16
17mod kw {
18 syn::custom_keyword!(class);
19}
20
21#[derive(Debug, Clone)]
22struct OverrideItem {
23 _override_token: Token![override],
24 override_class: Type,
25 _brace_token: Brace,
26 items: Vec<ImplItemFn>,
27}
28
29fn correct_priv_vis(vis: Visibility) -> Visibility {
30 match vis {
31 Visibility::Public(p) => Visibility::Public(p),
32 Visibility::Restricted(mut restricted) => {
33 if restricted.path.segments.get(0) != Some(&parse_quote!(crate)) {
34 restricted.path.segments.insert(0, parse_quote!(super));
35 }
36 Visibility::Restricted(restricted)
37 }
38 Visibility::Inherited => {
39 parse_quote!(pub(super))
40 }
41 }
42}
43
44impl Parse for OverrideItem {
45 fn parse(input: ParseStream) -> syn::Result<Self> {
46 let content;
47 let override_token = input.parse()?;
48 let override_class = input.parse()?;
49 let brace_token = braced!(content in input);
50 let mut items = Vec::new();
51 while !content.is_empty() {
52 let mut item: ImplItemFn = content.parse()?;
53 item.vis = correct_priv_vis(item.vis);
54 items.push(item);
55 }
56
57 Ok(OverrideItem {
58 _override_token: override_token,
59 override_class,
60 _brace_token: brace_token,
61 items,
62 })
63 }
64}
65
66#[derive(Debug, Clone)]
67enum ClassItem {
68 Field {
69 field: Field,
70 _semi_token: Token![;],
71 },
72 ImplItemFn(ImplItemFn),
73 OverrideItem(OverrideItem),
74}
75
76impl Parse for ClassItem {
77 fn parse(input: ParseStream) -> syn::Result<Self> {
78 let lookahead = input.lookahead1();
79 if lookahead.peek(Token![override]) {
80 return Ok(ClassItem::OverrideItem(OverrideItem::parse(input)?));
81 }
82
83 let begin = input.fork();
84 let _attrs = input.call(Attribute::parse_outer)?;
85 let _vis: Visibility = begin.parse()?;
86 let lookahead = begin.lookahead1();
87 if lookahead.peek(Token![fn])
88 || lookahead.peek(Token![unsafe])
89 || lookahead.peek(Token![async])
90 {
91 return Ok(ClassItem::ImplItemFn(ImplItemFn::parse(input)?));
92 }
93
94 let mut field = Field::parse_named(input)?;
95 field.vis = correct_priv_vis(field.vis);
96 let semi_token = input.parse()?;
97 Ok(ClassItem::Field {
98 field,
99 _semi_token: semi_token,
100 })
101 }
102}
103
104#[derive(Debug, Clone)]
105struct SuperclassInput {
106 _colon_token: Token![:],
107 ty: Type,
108}
109
110impl Parse for SuperclassInput {
111 fn parse(input: ParseStream) -> syn::Result<Self> {
112 Ok(SuperclassInput {
113 _colon_token: input.parse()?,
114 ty: input.parse()?,
115 })
116 }
117}
118
119#[derive(Debug, Clone)]
120struct ClassInput {
121 attrs: Vec<Attribute>,
122 vis: Visibility,
123 _class_token: kw::class,
124 ident: Ident,
125 superclass: Option<SuperclassInput>,
126 _brace_token: Brace,
127 items: Vec<ClassItem>,
128}
129
130impl Parse for ClassInput {
131 fn parse(input: ParseStream) -> syn::Result<Self> {
132 let attrs = input.call(Attribute::parse_outer)?;
133 let content;
134 let vis = input.parse()?;
135 let class_token = input.parse()?;
136 let ident = input.parse()?;
137
138 let lookahead = input.lookahead1();
139 let superclass = if lookahead.peek(Token![:]) {
140 Some(input.parse()?)
141 } else {
142 None
143 };
144
145 let brace_token = braced!(content in input);
146 let mut items = Vec::new();
147 while !content.is_empty() {
148 items.push(content.parse()?);
149 }
150 Ok(ClassInput {
151 attrs,
152 vis,
153 _class_token: class_token,
154 ident,
155 superclass,
156 _brace_token: brace_token,
157 items,
158 })
159 }
160}
161
162#[derive(Debug, Clone)]
163struct CrateAlias {
164 _crate_token: Token![crate],
165 _as_token: Token![as],
166 ident: Ident,
167 _semi_token: Token![;],
168}
169
170impl Parse for CrateAlias {
171 fn parse(input: ParseStream) -> syn::Result<Self> {
172 Ok(CrateAlias {
173 _crate_token: input.parse()?,
174 _as_token: input.parse()?,
175 ident: input.parse()?,
176 _semi_token: input.parse()?,
177 })
178 }
179}
180
181struct ClassInputs {
182 crate_alias: Option<CrateAlias>,
183 inputs: Vec<ClassInput>,
184}
185
186impl Parse for ClassInputs {
187 fn parse(input: ParseStream) -> syn::Result<Self> {
188 let lookahead = input.lookahead1();
189 let crate_alias = if lookahead.peek(Token![crate]) {
190 Some(input.parse()?)
191 } else {
192 None
193 };
194
195 let mut inputs = Vec::new();
196 while !input.is_empty() {
197 inputs.push(input.parse()?);
198 }
199
200 Ok(ClassInputs {
201 crate_alias,
202 inputs,
203 })
204 }
205}
206
207fn plusplus() -> proc_macro2::TokenStream {
208 let found_crate = crate_name("plusplus").expect("plusplus is present in `Cargo.toml`");
209 match found_crate {
210 FoundCrate::Itself => quote!(crate),
211 FoundCrate::Name(name) => {
212 let ident = Ident::new(&name, Span::call_site());
213 quote!( #ident )
214 }
215 }
216}
217
218fn cast_class_ptr(
219 plusplus: &proc_macro2::TokenStream,
220 from: &Type,
221 to: &Type,
222 expr: impl Into<proc_macro2::TokenStream>,
223) -> proc_macro2::TokenStream {
224 let expr = expr.into();
225 quote! {{
226 let t: &#from = #expr;
227 let self_size = std::mem::size_of_val(t);
228 let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
229 assert!(self_size >= target_size);
230 let array_size = self_size - target_size;
231 let target_ptr = std::ptr::slice_from_raw_parts(t as *const #from as *const u8, array_size);
232 let target_ref = &*(target_ptr as *const #to);
233 assert_eq!(self_size, std::mem::size_of_val(target_ref));
234 target_ref
235 }}
236}
237
238fn cast_class_ptr_mut(
239 plusplus: &TokenStream,
240 from: &Type,
241 to: &Type,
242 expr: impl Into<TokenStream>,
243) -> TokenStream {
244 let expr = expr.into();
245 quote! {{
246 let t: &mut #from = #expr;
247 let self_size = std::mem::size_of_val(t);
248 let target_size = std::mem::size_of::<#to<#plusplus::InConstruction>>();
249 assert!(self_size >= target_size);
250 let array_size = self_size - target_size;
251 let target_ptr = std::ptr::slice_from_raw_parts_mut(t as *mut #from as *mut u8, array_size);
252 let target_ref = &mut *(target_ptr as *mut #to);
253 assert_eq!(self_size, std::mem::size_of_val(target_ref));
254 target_ref
255 }}
256}
257
258fn set_arg_blank_lifetime(arg: &mut FnArg, lifetime: &Lifetime, lifetime_set: &mut bool) {
259 match arg {
260 FnArg::Receiver(rx) => {
261 if let Some((_, lt)) = &mut rx.reference {
262 maybe_set_lifetime_opt(lt, lifetime, lifetime_set);
263 }
264 }
265 FnArg::Typed(ty) => {
266 set_blank_type_lifetimes(&mut ty.ty, lifetime, lifetime_set);
267 }
268 }
269}
270
271fn set_blank_type_lifetimes(ty: &mut Type, lifetime: &Lifetime, lifetime_set: &mut bool) {
272 match ty {
273 Type::Array(arr) => set_blank_type_lifetimes(&mut arr.elem, lifetime, lifetime_set),
274 Type::BareFn(_) => {}
275 Type::Group(group) => set_blank_type_lifetimes(&mut group.elem, lifetime, lifetime_set),
276 Type::ImplTrait(_) => {} Type::Infer(_) => {}
278 Type::Macro(_) => {}
279 Type::Never(_) => {}
280 Type::Paren(paren) => set_blank_type_lifetimes(&mut paren.elem, lifetime, lifetime_set),
281 Type::Path(path) => {
282 if let Some(qself) = &mut path.qself {
283 set_blank_type_lifetimes(&mut qself.ty, lifetime, lifetime_set);
284 }
285 set_blank_path_lifetimes(&mut path.path, lifetime, lifetime_set);
286 }
287 Type::Ptr(ptr) => set_blank_type_lifetimes(&mut ptr.elem, lifetime, lifetime_set),
288 Type::Reference(refer) => {
289 maybe_set_lifetime_opt(&mut refer.lifetime, lifetime, lifetime_set);
290 set_blank_type_lifetimes(&mut refer.elem, lifetime, lifetime_set)
291 }
292 Type::Slice(slice) => set_blank_type_lifetimes(&mut slice.elem, lifetime, lifetime_set),
293 Type::TraitObject(obj) => {
294 set_blank_type_param_bounds(&mut obj.bounds, lifetime, lifetime_set)
295 }
296 Type::Tuple(tup) => {
297 for ty in &mut tup.elems {
298 set_blank_type_lifetimes(ty, lifetime, lifetime_set);
299 }
300 }
301 Type::Verbatim(_) => {}
302 _ => (),
303 }
304}
305
306fn set_blank_path_lifetimes(path: &mut Path, lifetime: &Lifetime, lifetime_set: &mut bool) {
307 for path_args in path.segments.iter_mut().map(|seg| &mut seg.arguments) {
308 match path_args {
309 PathArguments::None => {}
310 PathArguments::AngleBracketed(angle_args) => {
311 set_blank_angle_bracket_lifetimes(angle_args, lifetime, lifetime_set)
312 }
313 PathArguments::Parenthesized(paren_args) => {
314 for ty in &mut paren_args.inputs {
315 set_blank_type_lifetimes(ty, lifetime, lifetime_set);
316 }
317 if let ReturnType::Type(_, ty) = &mut paren_args.output {
318 set_blank_type_lifetimes(ty, lifetime, lifetime_set);
319 }
320 }
321 }
322 }
323}
324
325fn set_blank_angle_bracket_lifetimes(
326 angle: &mut AngleBracketedGenericArguments,
327 lifetime: &Lifetime,
328 lifetime_set: &mut bool,
329) {
330 for arg in &mut angle.args {
331 set_blank_generic_lifetimes(arg, lifetime, lifetime_set);
332 }
333}
334
335fn maybe_set_lifetime(set: &mut Lifetime, to: &Lifetime, lifetime_set: &mut bool) {
336 if set.ident == format_ident!("_") {
337 *set = to.clone();
338 *lifetime_set = true;
339 }
340}
341fn maybe_set_lifetime_opt(set: &mut Option<Lifetime>, to: &Lifetime, lifetime_set: &mut bool) {
342 match set {
343 Some(lt) => maybe_set_lifetime(lt, to, lifetime_set),
344 None => {
345 *set = Some(to.clone());
346 *lifetime_set = true;
347 }
348 }
349}
350
351fn set_blank_type_param_bounds<'a>(
352 bounds: impl IntoIterator<Item = &'a mut TypeParamBound>,
353 lifetime: &Lifetime,
354 lifetime_set: &mut bool,
355) {
356 for bound in bounds {
357 match bound {
358 TypeParamBound::Trait(trait_bound) => {
359 set_blank_path_lifetimes(&mut trait_bound.path, lifetime, lifetime_set)
360 }
361 TypeParamBound::Lifetime(lt) => maybe_set_lifetime(lt, lifetime, lifetime_set),
362 TypeParamBound::PreciseCapture(cap) => {
363 for p in &mut cap.params {
364 match p {
365 CapturedParam::Lifetime(lt) => {
366 maybe_set_lifetime(lt, lifetime, lifetime_set)
367 }
368 CapturedParam::Ident(_) => {}
369 _ => (),
370 }
371 }
372 }
373 TypeParamBound::Verbatim(_) => {}
374 _ => (),
375 }
376 }
377}
378fn set_blank_generic_lifetimes(
379 arg: &mut GenericArgument,
380 lifetime: &Lifetime,
381 lifetime_set: &mut bool,
382) {
383 match arg {
384 GenericArgument::Lifetime(lt) => maybe_set_lifetime(lt, lifetime, lifetime_set),
385 GenericArgument::Type(ty) => set_blank_type_lifetimes(ty, lifetime, lifetime_set),
386 GenericArgument::Const(_) => {}
387 GenericArgument::AssocType(ty) => {
388 if let Some(args) = &mut ty.generics {
389 set_blank_angle_bracket_lifetimes(args, lifetime, lifetime_set);
390 }
391 set_blank_type_lifetimes(&mut ty.ty, lifetime, lifetime_set);
392 }
393 GenericArgument::AssocConst(_) => {}
394 GenericArgument::Constraint(constraint) => {
395 if let Some(args) = &mut constraint.generics {
396 set_blank_angle_bracket_lifetimes(args, lifetime, lifetime_set);
397 }
398
399 set_blank_type_param_bounds(&mut constraint.bounds, lifetime, lifetime_set);
400 }
401 _ => (),
402 }
403}
404
405#[derive(Debug, Clone)]
406struct FuncInfo {
407 func: ImplItemFn,
408 name: Ident,
409 vtbl_name: Ident,
410 lifetime_bounds: Option<TokenStream>,
411 vtbl_sig: TokenStream,
412 args: Vec<Box<Pat>>,
413 mut_self: bool,
414}
415
416fn get_func_sig(class_name: &Type, f: &ImplItemFn) -> FuncInfo {
417 let func_name = &f.sig.ident;
418 let is_async = f.sig.asyncness.is_some();
419
420 let mut inputs = f.sig.inputs.clone();
421 let mut mut_self = false;
422 if let Some(FnArg::Receiver(rx)) = &f.sig.inputs.get(0) {
423 let receiver = &mut inputs[0];
424 if let Some((_, rx_lifetime)) = &rx.reference {
425 if rx.mutability.is_some() {
426 *receiver = FnArg::Typed(parse_quote!(this: & #rx_lifetime mut #class_name));
427 } else {
428 *receiver = FnArg::Typed(parse_quote!(this: & #rx_lifetime #class_name));
429 }
430 }
431 mut_self = rx.mutability.is_some();
432 };
433
434 let mut lifetimes: Vec<LifetimeParam> = Vec::new();
435 let future_fallback_lt: Lifetime = parse_quote!('rpp_future);
436 let mut using_future_lifetime = false;
437 let mut vtbl_inputs = inputs.clone();
438 if is_async {
440 for arg in &mut vtbl_inputs {
441 set_arg_blank_lifetime(arg, &future_fallback_lt, &mut using_future_lifetime);
442 }
443 if using_future_lifetime {
444 lifetimes.push(parse_quote!(#future_fallback_lt));
445 }
446 }
447 for generic in &f.sig.generics.params {
448 match generic {
449 GenericParam::Lifetime(lt) => {
450 let mut lt = lt.clone();
451 if using_future_lifetime {
452 lt.bounds.push(future_fallback_lt.clone());
453 }
454 lifetimes.push(lt)
455 }
461 GenericParam::Type(_) => {}
462 GenericParam::Const(_) => {}
463 }
464 }
465
466 let lifetime_bounds = if lifetimes.len() > 0 {
467 Some(quote!(<#(#lifetimes),*>))
468 } else {
469 None
470 };
471
472 let mut output = f.sig.output.clone();
473 if is_async {
474 let future_output = match output {
475 ReturnType::Default => quote!(()),
476 ReturnType::Type(_, ty) => quote!(#ty),
477 };
478 let future_lifetimes = if using_future_lifetime {
479 future_fallback_lt
480 } else {
481 assert!(lifetimes.len() > 0);
482 lifetimes[0].lifetime.clone()
483 };
484 output = parse_quote!(-> std::pin::Pin<Box<dyn #future_lifetimes + Future<Output=#future_output>>>);
485 }
486 let vtbl_name = format_ident!("fn_{func_name}");
487 let vtbl_sig = quote! {
488 (#vtbl_inputs) #output
489 };
490
491 let func_args = inputs
492 .into_iter()
493 .skip(1)
494 .map(|arg| match arg {
495 FnArg::Receiver(_) => unreachable!(),
496 FnArg::Typed(arg) => arg.pat,
497 })
498 .collect::<Vec<_>>();
499
500 FuncInfo {
501 func: f.clone(),
502 name: func_name.clone(),
503 vtbl_name,
504 lifetime_bounds,
505 vtbl_sig,
506 args: func_args,
507 mut_self,
508 }
509}
510
511#[derive(Debug, Clone, Copy)]
512struct Derives {
513 clone: bool,
514}
515
516impl Derives {
517 fn from_attributes(attrs: impl Iterator<Item = Attribute>) -> syn::Result<Derives> {
518 let mut clone = false;
519 for attr in attrs {
520 if let AttrStyle::Inner(_) = attr.style {
521 return Err(Error::new(
522 attr.span(),
523 "did not expect inner attribute in class macro",
524 ));
525 }
526
527 let derive_tokens = match attr.meta {
528 Meta::List(list) if list.path == parse_quote!(derive) => {
529 if !matches!(list.delimiter, MacroDelimiter::Paren(_)) {
530 return Err(Error::new(
531 list.delimiter.span().open(),
532 "derive attribute must have parenthesis",
533 ));
534 }
535 list.tokens
536 }
537 _ => return Err(Error::new(attr.span(), "unsupported attribute on class")),
538 };
539
540 let derive_path: Path = parse2(derive_tokens)?;
541 if derive_path == parse_quote!(Clone) {
542 if clone {
543 return Err(Error::new(
544 derive_path.span(),
545 "Clone derive already specified",
546 ));
547 }
548 clone = true;
549 }
550 }
551
552 Ok(Derives { clone })
553 }
554
555 fn has_any_derives(&self) -> bool {
556 self.clone
557 }
558}
559
560struct ClassData {
561 plusplus: TokenStream,
562 class_name: Ident,
563 class_type: Type,
564 class_mod_name: Ident,
565 vtbl_ident: Ident,
566 class_vis: Visibility,
567 fields: Vec<Field>,
568 constructors: Vec<FuncInfo>,
569 member_funcs: Vec<FuncInfo>,
570 overrides: Vec<OverrideItem>,
571 override_funcs: Vec<FuncInfo>,
572 superclass_type: Option<Type>,
573 mod_superclass_type: Option<Type>,
574 derives: Derives,
575}
576
577impl ClassData {
578 fn from_input(input: ClassInput, crate_alias: Option<&CrateAlias>) -> syn::Result<ClassData> {
579 let ClassInput {
580 attrs,
581 vis: class_vis,
582 _class_token: _,
583 ident: class_name,
584 superclass,
585 _brace_token: _,
586 items: class_items,
587 } = input;
588
589 let mut fields = Vec::new();
590 let mut constructors = Vec::new();
591 let mut member_funcs = Vec::new();
592 let mut overrides = Vec::new();
593 let mut override_funcs = Vec::new();
594
595 let class_type: Type = parse_quote!(#class_name);
596
597 for item in class_items {
598 match item {
599 ClassItem::Field { field, .. } => fields.push(field),
600 ClassItem::ImplItemFn(func) => {
601 if let Some(FnArg::Receiver(_)) = func.sig.inputs.get(0) {
602 member_funcs.push(get_func_sig(&class_type, &func))
603 } else {
604 constructors.push(get_func_sig(&class_type, &func));
605 }
606 }
607 ClassItem::OverrideItem(override_item) => {
608 override_funcs.extend(
609 override_item
610 .items
611 .iter()
612 .map(|f| get_func_sig(&class_type, &f)),
613 );
614 overrides.push(override_item);
615 }
616 }
617 }
618
619 let class_mod_name =
620 format_ident!("plusplus__class_{}", class_name.to_string().to_lowercase());
621
622 let plusplus = if let Some(alias) = crate_alias {
623 let alias = &alias.ident;
624 quote!(#alias)
625 } else {
626 plusplus()
627 };
628
629 let superclass_type = superclass.map(|sc| sc.ty);
630 let mod_superclass_type = match superclass_type.clone() {
631 Some(Type::Path(mut type_path)) => {
632 if type_path.path.segments.get(0) != Some(&parse_quote!(crate)) {
633 type_path.path.segments.insert(0, parse_quote!(super));
634 }
635 Some(Type::Path(type_path))
636 }
637 ty => ty,
638 };
639
640 let derives = Derives::from_attributes(attrs.into_iter())?;
641
642 Ok(ClassData {
643 plusplus,
644 vtbl_ident: format_ident!("{}Vtbl", class_name),
645 class_vis,
646 class_name,
647 class_type,
648 class_mod_name,
649 fields,
650 constructors,
651 member_funcs,
652 overrides,
653 override_funcs,
654 superclass_type,
655 mod_superclass_type,
656 derives,
657 })
658 }
659
660 fn has_superclass(&self) -> bool {
661 self.superclass_type.is_some()
662 }
663
664 fn gen_mod_vtbl_struct(&self) -> TokenStream {
665 let vtbl_ident = &self.vtbl_ident;
667 let class_name = &self.class_name;
668 let plusplus = &self.plusplus;
669
670 let mut vtbl_func_names = Vec::new();
671 let mut vtbl_sigs = Vec::new();
672 let mut my_func_names = Vec::new();
673 let mut async_func_impls = Vec::new();
674 let mut func_setters = Vec::new();
675 let mut vtbl_fors = Vec::new();
676 let mut vtbl_unsafes = Vec::new();
677
678 for f in self.member_funcs.iter() {
679 let FuncInfo {
680 func:
681 ImplItemFn {
682 sig:
683 Signature {
684 asyncness,
685 unsafety,
686 ..
687 },
688 ..
689 },
690 name: func_name,
691 vtbl_name: vtbl_func_name,
692 lifetime_bounds,
693 vtbl_sig,
694 args,
695 mut_self: _,
696 } = f;
697 let my_func_name = format_ident!("my_{func_name}");
698 let vtbl_for = lifetime_bounds.as_ref().map(|bounds| quote!(for #bounds));
699 vtbl_fors.push(vtbl_for.clone());
700 vtbl_unsafes.push(unsafety);
701
702 if asyncness.is_some() {
703 async_func_impls.push(quote!{
704 let #my_func_name: #vtbl_for #unsafety fn #vtbl_sig = |this, #(#args)*| #unsafety {
706 Box::pin(#class_name::#my_func_name(this, #(#args)*))
707 };
708 });
709 func_setters.push(quote! {
710 #vtbl_func_name: #my_func_name,
711 })
712 } else {
713 func_setters.push(quote! {
714 #vtbl_func_name: #class_name::#my_func_name,
715 })
716 }
717
718 my_func_names.push(my_func_name);
719 vtbl_func_names.push(vtbl_func_name);
720 vtbl_sigs.push(vtbl_sig);
721 }
722
723 let vtbl_drop_field: Option<_>;
724 let vtbl_drop_func: Option<_>;
725 let vtbl_drop_set: Option<_>;
726 if !self.has_superclass() {
727 vtbl_drop_field = Some(quote! {
728 pub manually_drop: unsafe fn(*mut #class_name),
729 });
730 vtbl_drop_func = Some(quote! {
731 unsafe fn manually_drop(this: *mut #class_name) {
732 unsafe{ std::ptr::drop_in_place(this) }
733 }
734 });
735 vtbl_drop_set = Some(quote! {
736 manually_drop,
737 });
738 } else {
739 vtbl_drop_field = None;
740 vtbl_drop_func = None;
741 vtbl_drop_set = None;
742 };
743
744 let mut vtbl_trait_fields = None;
745 let mut vtbl_trait_impls = None;
746 let mut vtbl_trait_setters = None;
747 if self.derives.has_any_derives() && !self.has_superclass() {
748 let Derives { clone } = self.derives;
749 let clone_field = clone.then(|| {
750 quote! {
751 class_clone: fn(&#class_name) -> #plusplus::ClassBox<#class_name>,
752 }
753 });
754 let clone_impl = clone.then(|| {
755 quote! {
756 fn class_clone(this: &#class_name) -> #plusplus::ClassBox<#class_name> {
757 use #plusplus::{Class, ClassInConstruction};
758 let in_construction = unsafe{ this.as_in_construction() };
759 in_construction.clone().finish()
760 }
761 }
762 });
763 let clone_set = clone.then(|| {
764 quote! {
765 class_clone,
766 }
767 });
768 vtbl_trait_fields = Some(quote! {
769 #clone_field
770 });
771 vtbl_trait_impls = Some(quote! {
772 #clone_impl
773 });
774 vtbl_trait_setters = Some(quote! {
775 #clone_set
776 })
777 };
778
779 quote! {
780 #[doc(hidden)]
781 #[derive(Clone, Copy)]
782 pub struct #vtbl_ident {
783 #vtbl_drop_field
784 #vtbl_trait_fields
785 #(pub #vtbl_func_names: #vtbl_fors #vtbl_unsafes fn #vtbl_sigs,)*
786 }
787
788 impl #vtbl_ident {
789 const BASE: Self = {
790 #vtbl_drop_func
791 #vtbl_trait_impls
792 #(#async_func_impls)*
793
794 Self {
795 #vtbl_drop_set
796 #vtbl_trait_setters
797 #(#func_setters)*
798 }
799 };
800 }
801 }
802 }
803
804 fn gen_fn_set_vtbls(&self) -> TokenStream {
805 let plusplus = &self.plusplus;
806 let class_name = &self.class_name;
807
808 let set_vtbls = self.overrides.iter().map(|ovr| {
809 let ovr_class = &ovr.override_class;
810 let ovr_class = match ovr_class.clone() {
811 Type::Path(mut type_path) => {
812 type_path.path.segments.insert(0, parse_quote!(super));
813 Type::Path(type_path)
814 }
815 ty => ty,
816 };
817
818 let mut ol_func_names = Vec::new();
819 let mut ol_func_sigs = Vec::new();
820 let mut ol_func_self_call_impls = Vec::new();
821 let mut ol_lifetime_bounds = Vec::new();
822 for f in &ovr.items {
823 let FuncInfo {
824 func:
825 ImplItemFn {
826 sig:
827 Signature {
828 asyncness,
829 unsafety,
830 ..
831 },
832 ..
833 },
834 name: func_name,
835 vtbl_name,
836 lifetime_bounds,
837 vtbl_sig: func_sig,
838 args: func_args,
839 mut_self,
840 } = get_func_sig(&ovr_class, f);
841 ol_func_names.push(vtbl_name);
842 ol_func_sigs.push(func_sig);
843 ol_lifetime_bounds.push(lifetime_bounds);
844
845 let func_name = format_ident!("my_{}", func_name);
846 let make_this = if mut_self {
847 quote! {
848 let this: &mut #class_name = unsafe{ #class_name::from_root_class_mut(this.root_class_mut()) };
849 }
850 } else {
851 quote! {
852 let this: &#class_name = unsafe{ #class_name::from_root_class_ref(this.root_class()) };
853 }
854 };
855 let self_call = if asyncness.is_some() {
856 quote! {
857 #make_this
858 #unsafety { Box::pin(this.#func_name(#(#func_args,)*)) }
859 }
860 } else {
861 quote! {
862 #make_this
863 #unsafety { this.#func_name(#(#func_args,)*) }
864 }
865 };
866 ol_func_self_call_impls.push(self_call);
867 }
868
869 quote! {{
870 let this: &mut #ovr_class = &mut *(unsafe{ self.to_constructed() });
871 #(
872 fn #ol_func_names #ol_lifetime_bounds #ol_func_sigs {
873 #ol_func_self_call_impls
874 }
875 unsafe{ this.plusplus__vtbl_mut().#ol_func_names = #ol_func_names };
876 )*
877 }}
878 });
879
880 let root_type: Type = parse_quote!(<#class_name as #plusplus::Class>::RootClass);
881 let root_type = &root_type;
882
883 let set_subclass = self.has_superclass().then(|| quote!{
884 use #plusplus::Class as _;
885 unsafe{ self.superclass.plusplus__set_subclass(<#class_name as #plusplus::Class>::TYPE_ID) };
886
887 {
888 unsafe fn manually_drop(this: *mut #root_type) {
889 let this = unsafe{ #class_name::from_root_class_mut(&mut *this) };
890 unsafe{ std::ptr::drop_in_place(this) };
891 }
892 let root_vtbl = unsafe{ <#class_name as #plusplus::Class>::root_class_mut(self.to_constructed()).plusplus__vtbl_mut() };
893 root_vtbl.manually_drop = manually_drop;
894 }
895 });
896
897 let mut set_trait_vtbls = None;
898 if !self.has_superclass() {
899 let mut derive_trait_bounds = None;
900 let mut derive_trait_impls = None;
901 if self.derives.has_any_derives() {
902 let Derives { clone } = self.derives;
903 let clone_trait_bound = clone.then(|| quote!(Clone));
904 let clone_impl = clone.then(|| quote!{
905 let class_clone = |this: &#class_name| -> #plusplus::ClassBox<#class_name> {
906 use #plusplus::{Class as _, ClassBox, ClassInConstruction};
907 let child_class = unsafe{ Class::from_root_class_ref(this).as_in_construction() };
908 let cloned = child_class.clone().finish();
909 unsafe{ ClassBox::from_raw(ClassBox::leak(cloned).root_class_mut()) }
910 };
911 self.vtbl.class_clone = class_clone;
912 });
913 derive_trait_bounds =
914 Some(quote! {where Class::InConstruction: #clone_trait_bound});
915 derive_trait_impls = Some(quote! {
916 #clone_impl
917 });
918 }
919
920 set_trait_vtbls = Some(quote! {
921 #[doc(hidden)]
922 pub fn plusplus__set_trait_vtbls<Class: ?Sized + #plusplus::Class<RootClass=#class_name>>(&mut self)
923 #derive_trait_bounds
924 {
925 #derive_trait_impls
926 }
927 });
928 }
929
930 quote! {
931 fn plusplus__set_vtbls(&mut self) {
932 #set_subclass
933 #(#set_vtbls)*
934 }
935
936 #set_trait_vtbls
937 }
938 }
939
940 fn gen_mod_class_struct(&self) -> TokenStream {
941 let plusplus = &self.plusplus;
942
943 let superclass_field = self.mod_superclass_type.as_ref().map(|sc_type| {
944 quote! {
945 superclass: #sc_type<#plusplus::InConstruction>,
946 }
947 });
948 let superclass_field = superclass_field.as_ref();
949 let superclass_bound = self.mod_superclass_type.as_ref().map(|sc_ident| {
950 quote! {
951 where #sc_ident: #plusplus::Class
952 }
953 });
954
955 let class_struct_vis = correct_priv_vis(self.class_vis.clone());
956 let vtbl_ident = &self.vtbl_ident;
957 let class_name = &self.class_name;
958 let fields = &self.fields;
959 let init_superclass_field = superclass_field.map(|f| quote!(pub #f));
960 let init_fields = self.fields.iter().cloned().map(|f| Field {
961 vis: Visibility::Public(parse_quote!(pub)),
962 ..f
963 });
964
965 let derives = self.derives.has_any_derives().then(|| {
966 let Derives { clone } = self.derives;
967 let clone = clone.then(|| quote!(Clone,));
968 quote!(#[derive(#clone)])
969 });
970
971 quote! {
972 #[repr(C)]
973 #derives
974 #class_struct_vis struct #class_name<C: ?Sized + #plusplus::ClassMemory = #plusplus::Constructed>
975 #superclass_bound
976 {
977 #superclass_field
978 vtbl: #vtbl_ident,
979 subclass_id: Option<&'static std::any::TypeId>,
982 #(#fields,)*
983 memory: C,
984 }
985
986 pub struct PlusPlus__InitClass {
987 #init_superclass_field
988 #(#init_fields,)*
989 }
990 }
991 }
992
993 fn gen_mod_trait_impls(&self) -> TokenStream {
994 let plusplus = &self.plusplus;
995 let class_name = &self.class_name;
996
997 let Derives { clone } = self.derives;
998
999 let clone_impl = clone.then(|| {
1000 if self.has_superclass() {
1001 quote! {
1002 impl #plusplus::ClassClone for #class_name {
1003 fn class_clone(&self) -> #plusplus::ClassBox<Self> {
1004 use #plusplus::{ClassBox, Class, ClassClone};
1005 let root_ref: &mut _ = ClassBox::leak(self.root_class().class_clone());
1006 let self_ref = unsafe{ Self::from_root_class_mut(root_ref) };
1007 unsafe{ ClassBox::from_raw(self_ref) }
1008 }
1009 }
1010 }
1011 } else {
1012 quote! {
1013 impl #plusplus::ClassClone for #class_name {
1014 fn class_clone(&self) -> #plusplus::ClassBox<Self> {
1015 (self.vtbl.class_clone)(self)
1016 }
1017 }
1018 }
1019 }
1020 });
1021
1022 quote! {
1023 #clone_impl
1024 }
1025 }
1026
1027 fn gen_superclass_casters(&self) -> Option<TokenStream> {
1028 let Some(sc_type) = self.superclass_type.as_ref() else {
1029 return None;
1030 };
1031 let class_name = &self.class_name;
1032
1033 let deref_upcast = cast_class_ptr(&self.plusplus, &self.class_type, sc_type, quote! {self});
1034 let deref_upcast_mut =
1035 cast_class_ptr_mut(&self.plusplus, &self.class_type, sc_type, quote! {self});
1036 let ref_downcast = cast_class_ptr(&self.plusplus, sc_type, &self.class_type, quote! {self});
1037 let ref_downcast_mut =
1038 cast_class_ptr_mut(&self.plusplus, sc_type, &self.class_type, quote! {self});
1039
1040 let plusplus = &self.plusplus;
1041 Some(quote! {
1042 impl std::ops::Deref for #class_name {
1043 type Target = #sc_type;
1044
1045 fn deref(&self) -> &Self::Target {
1046 unsafe { #deref_upcast }
1047 }
1048 }
1049
1050 impl std::ops::DerefMut for #class_name {
1051 fn deref_mut(&mut self) -> &mut Self::Target {
1052 unsafe { #deref_upcast_mut }
1053 }
1054 }
1055
1056 impl<'a> #plusplus::Downcast<#class_name> for &'a #sc_type {
1057 type Wrapped = &'a #class_name;
1058 fn downcast(self) -> Result<&'a #class_name, Self> {
1059 use #plusplus::Class;
1060 let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
1061 if self.subclass_id() == Some(subclass_type_id) {
1062 Ok(unsafe{ #ref_downcast })
1063 } else {
1064 Err(self)
1065 }
1066 }
1067 }
1068
1069 impl<'a> #plusplus::Downcast<#class_name> for &'a mut #sc_type {
1070 type Wrapped = &'a mut #class_name;
1071 fn downcast(self) -> Result<&'a mut #class_name, Self> {
1072 use #plusplus::Class;
1073 let subclass_type_id = <#class_name as #plusplus::Class>::TYPE_ID;
1074 if self.subclass_id() == Some(subclass_type_id) {
1075 Ok(unsafe{ #ref_downcast_mut })
1076 } else {
1077 Err(self)
1078 }
1079 }
1080 }
1081 })
1082 }
1083
1084 fn gen_mod_impl_class_trait(&self) -> TokenStream {
1085 let plusplus = &self.plusplus;
1086 let class_name = &self.class_name;
1087 let root_class = self
1088 .mod_superclass_type
1089 .as_ref()
1090 .map(|sc_ident| quote! { <#sc_ident as #plusplus::Class>::RootClass })
1091 .unwrap_or_else(|| quote! { #class_name });
1092
1093 let from_root_class_ref = cast_class_ptr(
1094 plusplus,
1095 &parse_quote!(#root_class),
1096 &parse_quote!(#class_name),
1097 quote!(root),
1098 );
1099 let from_root_class_mut = cast_class_ptr_mut(
1100 plusplus,
1101 &parse_quote!(#root_class),
1102 &parse_quote!(#class_name),
1103 quote!(root),
1104 );
1105
1106
1107 quote! {
1108 unsafe impl #plusplus::Class for #class_name {
1109 const TYPE_ID: &'static std::any::TypeId = &std::any::TypeId::of::<#class_name>();
1110
1111 type RootClass = #root_class;
1112 type InConstruction = #class_name<#plusplus::InConstruction>;
1113
1114 fn subclass_id(&self) -> Option<&'static std::any::TypeId> {
1115 self.subclass_id
1116 }
1117
1118 fn root_class(&self) -> &Self::RootClass {
1119 self
1120 }
1121
1122 fn root_class_mut(&mut self) -> &mut Self::RootClass {
1123 self
1124 }
1125
1126 unsafe fn manually_drop(slot: &mut std::mem::ManuallyDrop<Self>) {
1127 let as_root_class = slot.root_class_mut();
1128 let manual_drop_fn = unsafe{ as_root_class.plusplus__vtbl_mut().manually_drop };
1129 unsafe{ manual_drop_fn(as_root_class); }
1130 }
1131 unsafe fn as_in_construction(&self) -> &#class_name<#plusplus::InConstruction> {
1132 unsafe{ &*(self as *const Self as *const #class_name<#plusplus::InConstruction>) }
1133 }
1134 unsafe fn as_in_construction_mut(&mut self) -> &mut #class_name<#plusplus::InConstruction> {
1135 unsafe{ &mut *(self as *mut Self as *mut #class_name<#plusplus::InConstruction>) }
1136 }
1137 unsafe fn from_root_class_ref(root: &Self::RootClass) -> &Self {
1138 unsafe{ #from_root_class_ref }
1139 }
1140 unsafe fn from_root_class_mut(root: &mut Self::RootClass) -> &mut Self {
1141 unsafe{ #from_root_class_mut }
1142 }
1143 }
1144
1145 impl #plusplus::ClassInConstruction for #class_name<#plusplus::InConstruction> {
1146 type Class = #class_name;
1147
1148 fn finish(self) -> #plusplus::ClassBox<#class_name> {
1152 let boxed = Box::new(self);
1153 let leaked = Box::leak(boxed);
1154 let constructed = unsafe{ leaked.to_constructed() };
1155 unsafe{ #plusplus::ClassBox::from_raw(constructed) }
1156 }
1157 }
1158 }
1159 }
1160
1161 fn gen_mod_class_impl(&self) -> TokenStream {
1162 let class_name = &self.class_name;
1163 let vtbl_ident = &self.vtbl_ident;
1164
1165 let mut call_vtbl_impls = Vec::new();
1166 for f in self.member_funcs.iter() {
1167 let FuncInfo {
1168 func: ImplItemFn { vis, sig, .. },
1169 name: _,
1170 vtbl_name,
1171 lifetime_bounds: _,
1172 vtbl_sig: _,
1173 args: func_args,
1174 mut_self: _,
1175 } = f;
1176
1177 let vis = correct_priv_vis(vis.clone());
1178 let do_await = sig.asyncness.is_some().then(|| quote!(.await));
1179 let call_vtbl = quote! {
1180 #vis #sig {
1181 (self.vtbl.#vtbl_name)(self, #(#func_args,)*) #do_await
1182 }
1183 };
1184 call_vtbl_impls.push(call_vtbl);
1185 }
1186
1187 let mut my_func_impls = Vec::new();
1188 let mut super_func_impls = Vec::new();
1189
1190 for (f, is_override) in self
1191 .member_funcs
1192 .iter()
1193 .cloned()
1194 .map(|f| (f, false))
1195 .chain(self.override_funcs.iter().cloned().map(|f| (f, true)))
1196 {
1197 let FuncInfo {
1198 func:
1199 ImplItemFn {
1200 attrs: _,
1201 vis,
1202 defaultness: _,
1203 sig,
1204 block,
1205 },
1206 name: func_name,
1207 vtbl_name: _,
1208 lifetime_bounds: _,
1209 vtbl_sig: _,
1210 args: func_args,
1211 mut_self,
1212 } = f;
1213
1214 let my_impl_name = format_ident!("my_{}", func_name);
1215 let mut my_impl_sig = sig.clone();
1216 my_impl_sig.ident = my_impl_name.clone();
1217 my_func_impls.push(quote! {
1218 #vis #my_impl_sig {
1219 #block
1220 }
1221 });
1222
1223 if is_override {
1224 let super_impl_name = format_ident!("super_{}", func_name);
1225 let mut super_impl_sig = sig.clone();
1226 super_impl_sig.ident = super_impl_name.clone();
1227 let get_super = if mut_self {
1228 quote! {
1229 self.plusplus__super_mut()
1230 }
1231 } else {
1232 quote! {
1233 self.plusplus__super_ref()
1234 }
1235 };
1236 let super_impl_block = if sig.asyncness.is_some() {
1237 quote! { #get_super.#my_impl_name(#(#func_args,)*).await }
1238 } else {
1239 quote! { #get_super.#my_impl_name(#(#func_args,)*) }
1240 };
1241
1242 super_func_impls.push(quote! {
1243 #vis #super_impl_sig {
1244 #super_impl_block
1245 }
1246 });
1247 }
1248 }
1249
1250 let superclass_getters = self.mod_superclass_type.as_ref().map(|sc_ident| {
1251 quote! {
1252 fn plusplus__super_ref(&self) -> &#sc_ident {
1253 self
1254 }
1255
1256 fn plusplus__super_mut(&mut self) -> &mut #sc_ident {
1257 self
1258 }
1259 }
1260 });
1261
1262 quote! {
1263 impl #class_name {
1264 #(#call_vtbl_impls)*
1265 #(#super_func_impls)*
1266
1267 #superclass_getters
1268
1269 #[doc(hidden)]
1270 pub unsafe fn plusplus__vtbl_mut(&mut self) -> &mut #vtbl_ident {
1271 &mut self.vtbl
1272 }
1273 }
1274 }
1275 }
1276
1277 fn gen_mod_in_construction_class_impl(&self) -> TokenStream {
1278 let plusplus = &self.plusplus;
1279 let class_name = &self.class_name;
1280 let vtbl_ident = &self.vtbl_ident;
1281
1282 let set_vtbl_func = self.gen_fn_set_vtbls();
1283
1284 let superclass_field = self
1285 .has_superclass()
1286 .then(|| quote! {superclass: init.superclass,});
1287 let fields = self.fields.iter().map(|f| &f.ident).collect::<Vec<_>>();
1288
1289 quote! {
1290 impl #class_name<#plusplus::InConstruction> {
1291 #set_vtbl_func
1292
1293 pub(super) fn plusplus__new_from_init(init: PlusPlus__InitClass) -> Self {
1294 use #plusplus::Class;
1295 let mut this = Self {
1296 vtbl: #vtbl_ident::BASE,
1297 memory: #plusplus::InConstruction::default(),
1298 subclass_id: None,
1299 #superclass_field
1300 #(#fields: init.#fields,)*
1301 };
1302
1303 this.plusplus__set_vtbls();
1304 unsafe{ this.to_constructed().root_class_mut().as_in_construction_mut() }.plusplus__set_trait_vtbls::<#class_name>();
1305
1306 this
1307 }
1308
1309 #[doc(hidden)]
1310 pub unsafe fn plusplus__set_subclass(&mut self, subclass_id: &'static std::any::TypeId) {
1311 self.subclass_id = Some(subclass_id);
1312 }
1313
1314 pub unsafe fn to_constructed(&mut self) -> &mut #class_name {
1317 unsafe{ &mut *(std::ptr::slice_from_raw_parts_mut::<u8>(self as *mut _ as *mut u8, 0) as *mut #class_name) }
1318 }
1319 }
1320 }
1321 }
1322
1323 fn gen_init_class_macro(&self) -> TokenStream {
1324 let plusplus = &self.plusplus;
1325 let class_name = &self.class_name;
1326 let class_mod_name = &self.class_mod_name;
1327
1328 quote! {
1329 macro_rules! init_class {
1330 ($($tt:tt)*) => {{
1331 #class_name::<#plusplus::InConstruction>::plusplus__new_from_init(#class_mod_name::PlusPlus__InitClass {
1332 $($tt)*
1333 })
1334 }}
1335 }
1336 }
1337 }
1338
1339 fn gen_class_impl(&self) -> TokenStream {
1340 let class_name = &self.class_name;
1341 let mut my_func_impls = Vec::new();
1342 for f in self
1343 .member_funcs
1344 .iter()
1345 .cloned()
1346 .chain(self.override_funcs.iter().cloned())
1347 {
1348 let FuncInfo {
1349 func:
1350 ImplItemFn {
1351 attrs: _,
1352 vis,
1353 defaultness: _,
1354 sig,
1355 block,
1356 },
1357 name: func_name,
1358 vtbl_name: _,
1359 lifetime_bounds: _,
1360 vtbl_sig: _,
1361 args: _,
1362 mut_self: _,
1363 } = f;
1364
1365 let my_impl_name = format_ident!("my_{}", func_name);
1366 let mut my_impl_sig = sig.clone();
1367 my_impl_sig.ident = my_impl_name.clone();
1368 my_func_impls.push(quote! {
1369 #vis #my_impl_sig {
1370 #block
1371 }
1372 });
1373 }
1374
1375 let init_class_macro = self.gen_init_class_macro();
1376 let mut constructor_impls = Vec::new();
1377 for c in self.constructors.iter() {
1378 let ImplItemFn {
1379 attrs,
1380 vis,
1381 defaultness,
1382 sig,
1383 block,
1384 } = &c.func;
1385
1386 let vis = correct_priv_vis(vis.clone());
1387 constructor_impls.push(quote! {
1388 #(#attrs)* #vis #defaultness #sig {
1389 #init_class_macro
1390 #block
1391 }
1392 });
1393 }
1394
1395 quote! {
1396 impl #class_name {
1397 #(#constructor_impls)*
1398 #(#my_func_impls)*
1399 }
1400 }
1401 }
1402
1403 fn gen_class(&self) -> TokenStream {
1404 let class_vis = &self.class_vis;
1405 let class_name = &self.class_name;
1406 let class_mod_name = &self.class_mod_name;
1407 let mod_vtbl_struct = self.gen_mod_vtbl_struct();
1408 let mod_class_struct = self.gen_mod_class_struct();
1409 let mod_impl_class_trait = self.gen_mod_impl_class_trait();
1410 let mod_trait_impls = self.gen_mod_trait_impls();
1411 let superclass_cast = self.gen_superclass_casters();
1412 let mod_class_impl = self.gen_mod_class_impl();
1413 let mod_in_construction_class_impl = self.gen_mod_in_construction_class_impl();
1414 let class_impl = self.gen_class_impl();
1415
1416 quote! {
1417 #class_vis use #class_mod_name::#class_name;
1418 mod #class_mod_name {
1419 use super::*;
1420 #mod_vtbl_struct
1421 #mod_class_struct
1422
1423 #mod_class_impl
1424
1425 #mod_impl_class_trait
1426
1427 #mod_in_construction_class_impl
1428
1429 #mod_trait_impls
1430 }
1431
1432 #class_impl
1433
1434 #superclass_cast
1435 }
1436 }
1437}
1438
1439fn do_class(inputs: ClassInputs) -> syn::Result<TokenStream> {
1440 let class_data = inputs
1441 .inputs
1442 .into_iter()
1443 .map(|input| Ok(ClassData::from_input(input, inputs.crate_alias.as_ref())?.gen_class()))
1444 .collect::<Result<Vec<_>, syn::Error>>()?;
1445
1446 Ok(quote! {
1447 #(#class_data)*
1448 })
1449}
1450
1451#[proc_macro]
1453pub fn class(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
1454 let inputs = parse_macro_input!(tokens as ClassInputs);
1455 do_class(inputs)
1456 .unwrap_or_else(syn::Error::into_compile_error)
1457 .into()
1458}