1
1
use darling:: FromField ;
2
2
use proc_macro2:: TokenStream ;
3
- use quote:: { format_ident, quote, ToTokens } ;
3
+ use quote:: { format_ident, quote} ;
4
4
use syn:: { DataStruct , Ident , Result } ;
5
5
6
6
use crate :: {
@@ -26,41 +26,82 @@ pub(crate) struct VersionedStruct {
26
26
pub ( crate ) fields : Vec < VersionedField > ,
27
27
}
28
28
29
- impl ToTokens for VersionedStruct {
30
- fn to_tokens ( & self , _tokens : & mut TokenStream ) {
31
- let mut versions = self . versions . iter ( ) . peekable ( ) ;
29
+ impl ToTokensExt < bool > for VersionedStruct {
30
+ fn to_tokens ( & self , generate_modules : bool ) -> Option < TokenStream > {
31
+ // TODO (@Techassi): This unwrap should be fine, should we expect here?
32
+ let mut versions = self . versions . clone ( ) ;
33
+ versions. pop ( ) . unwrap ( ) ;
34
+ let mut versions = versions. iter ( ) . peekable ( ) ;
32
35
36
+ let mut tokens = TokenStream :: new ( ) ;
37
+
38
+ // TODO (@Techassi): Move this into own functions
33
39
while let Some ( version) = versions. next ( ) {
34
- let mut fields = TokenStream :: new ( ) ;
40
+ let mut field_tokens = TokenStream :: new ( ) ;
35
41
36
42
for field in & self . fields {
37
- fields . extend ( field. to_tokens_for_version ( version) ) ;
43
+ field_tokens . extend ( field. to_tokens ( version) ) ;
38
44
}
39
45
40
- // TODO (@Techassi): Make the generation of the module optional to
41
- // enable the attribute macro to be applied to a module which
42
- // generates versioned versions of all contained containers.
43
-
44
- let deprecated_attr = version. deprecated . then_some ( quote ! { #[ deprecated] } ) ;
45
46
let module_name = format_ident ! ( "{version}" , version = version. inner. to_string( ) ) ;
47
+ let deprecated_attr = version. deprecated . then_some ( quote ! { #[ deprecated] } ) ;
46
48
let struct_name = & self . ident ;
47
49
48
- // Only generate a module when there is at least one more version.
49
- // This skips generating a module for the latest version, because
50
- // the base struct always represents the latest version.
51
- if versions. peek ( ) . is_some ( ) {
52
- _tokens. extend ( quote ! {
50
+ let struct_tokens = quote ! {
51
+ pub struct #struct_name {
52
+ #field_tokens
53
+ }
54
+ } ;
55
+
56
+ // Only generate modules when asked to do so by the caller. This
57
+ // enables us the support attribute macros to generate code for
58
+ // multiple versioned containers in a single file (no module name
59
+ // collition).
60
+ if generate_modules {
61
+ // Only generate a module when there is at least one more
62
+ // version. This skips generating a module for the latest
63
+ // version, because the base struct always represents the
64
+ // latest version.
65
+ tokens. extend ( quote ! {
53
66
#[ automatically_derived]
54
67
#deprecated_attr
55
68
pub mod #module_name {
56
-
57
- pub struct #struct_name {
58
- #fields
59
- }
69
+ #struct_tokens
60
70
}
61
71
} ) ;
72
+
73
+ if let Some ( next) = versions. peek ( ) {
74
+ // Generate From<THIS> for NEXT impls
75
+ let next_module = format_ident ! ( "{}" , next. inner. to_string( ) ) ;
76
+
77
+ let from_impl_tokens = quote ! {
78
+ #[ automatically_derived]
79
+ impl From <#module_name:: #struct_name> for #next_module:: #struct_name {
80
+ fn from( from: #module_name:: #struct_name) -> Self {
81
+ todo!( ) ;
82
+ }
83
+ }
84
+ } ;
85
+
86
+ tokens. extend ( from_impl_tokens) ;
87
+ } else {
88
+ let from_impl_tokens = quote ! {
89
+ #[ automatically_derived]
90
+ impl From <#module_name:: #struct_name> for #struct_name {
91
+ fn from( from: #module_name:: #struct_name) -> Self {
92
+ todo!( ) ;
93
+ }
94
+ }
95
+ } ;
96
+
97
+ tokens. extend ( from_impl_tokens) ;
98
+ }
99
+ } else {
100
+ tokens. extend ( struct_tokens)
62
101
}
63
102
}
103
+
104
+ Some ( tokens)
64
105
}
65
106
}
66
107
0 commit comments