@@ -11,23 +11,24 @@ use syn::{
1111 Parse ,
1212 ParseStream ,
1313 } ,
14+ parse_quote,
1415 punctuated:: Punctuated ,
1516 spanned:: Spanned ,
16- Attribute ,
1717 Error ,
1818 Expr ,
1919 Field ,
20- FieldsNamed ,
20+ Fields ,
21+ GenericArgument ,
2122 GenericParam ,
22- Generics ,
2323 Ident ,
24+ ItemStruct ,
2425 Lit ,
2526 LitStr ,
2627 MetaNameValue ,
2728 Path ,
29+ PathArguments ,
2830 Result ,
2931 Token ,
30- Visibility ,
3132} ;
3233
3334struct StaticIdent ( & ' static str ) ;
@@ -97,6 +98,7 @@ impl Parse for FieldArgs {
9798#[ derive( Debug ) ]
9899struct StructArgs {
99100 memory : Option < TokenStream > ,
101+ inherits : Option < Path > ,
100102}
101103
102104impl Parse for StructArgs {
@@ -106,6 +108,7 @@ impl Parse for StructArgs {
106108
107109 let mut size = None ;
108110 let mut memory = None ;
111+ let mut inherits = None ;
109112
110113 for kv in & vars {
111114 if kv. path . is_ident ( "size" ) {
@@ -121,6 +124,11 @@ impl Parse for StructArgs {
121124 Lit :: Str ( value) => memory = Some ( value. parse :: < Expr > ( ) ?. to_token_stream ( ) ) ,
122125 _ => return Err ( Error :: new ( kv. lit . span ( ) , "expected a string" ) ) ,
123126 }
127+ } else if kv. path . is_ident ( "inherits" ) {
128+ match & kv. lit {
129+ Lit :: Str ( value) => inherits = Some ( value. parse :: < Path > ( ) ?) ,
130+ _ => return Err ( Error :: new ( kv. lit . span ( ) , "expected a string" ) ) ,
131+ }
124132 } else {
125133 return Err ( Error :: new ( kv. path . span ( ) , "unknown attribute" ) ) ;
126134 }
@@ -129,11 +137,41 @@ impl Parse for StructArgs {
129137 let size = size. map ( |size : TokenStream | quote:: quote!( [ u8 ; #size] ) . to_token_stream ( ) ) ;
130138 Ok ( Self {
131139 memory : memory. or ( size) ,
140+ inherits,
132141 } )
133142 }
134143}
135144
136- fn extract_struct_fields ( fields : & FieldsNamed ) -> Result < Vec < ( FieldArgs , Field ) > > {
145+ fn add_type_param ( path : & mut Path , ty : syn:: Type ) {
146+ if let Some ( last) = path. segments . last_mut ( ) {
147+ match & mut last. arguments {
148+ PathArguments :: None => {
149+ // Turn `None` into `<T>`
150+ last. arguments =
151+ PathArguments :: AngleBracketed ( syn:: AngleBracketedGenericArguments {
152+ colon2_token : None ,
153+ lt_token : Default :: default ( ) ,
154+ args : vec ! [ GenericArgument :: Type ( ty) ] . into_iter ( ) . collect ( ) ,
155+ gt_token : Default :: default ( ) ,
156+ } ) ;
157+ }
158+ PathArguments :: AngleBracketed ( args) => {
159+ // Already has <...>, just push
160+ args. args . push ( GenericArgument :: Type ( ty) ) ;
161+ }
162+ PathArguments :: Parenthesized ( _) => {
163+ // Function-like path segment, can't add normal type params
164+ panic ! ( "cannot add type arguments to a function-like path segment" ) ;
165+ }
166+ }
167+ }
168+ }
169+
170+ fn extract_struct_fields ( fields : & Fields ) -> Result < Vec < ( FieldArgs , Field ) > > {
171+ let Fields :: Named ( fields) = fields else {
172+ return Err ( Error :: new ( fields. span ( ) , "only named fields supported" ) ) ;
173+ } ;
174+
137175 let mut result = Vec :: with_capacity ( fields. named . len ( ) ) ;
138176 for field in fields. named . iter ( ) {
139177 let mut field = field. clone ( ) ;
@@ -198,41 +236,7 @@ fn generate_reference_accessors(fields: &[(FieldArgs, Field)]) -> Result<TokenSt
198236 . into_token_stream ( ) )
199237}
200238
201- #[ derive( Debug ) ]
202- #[ allow( unused) ]
203- pub struct ItemRawStruct {
204- pub attrs : Vec < Attribute > ,
205- pub vis : Visibility ,
206- pub struct_token : Token ! [ struct ] ,
207- pub ident : Ident ,
208- pub generics : Generics ,
209- pub super_class : Option < ( Token ! [ : ] , Path ) > ,
210- pub fields : FieldsNamed ,
211- pub semi_token : Option < Token ! [ ; ] > ,
212- }
213-
214- impl Parse for ItemRawStruct {
215- fn parse ( input : ParseStream ) -> Result < Self > {
216- Ok ( Self {
217- attrs : input. call ( Attribute :: parse_outer) ?,
218- vis : input. parse ( ) ?,
219- struct_token : input. parse ( ) ?,
220- ident : input. parse ( ) ?,
221- generics : input. parse ( ) ?,
222- super_class : if input. peek ( Token ! [ : ] ) {
223- let colon: Token ! [ : ] = input. parse ( ) ?;
224- let path: Path = input. parse ( ) ?;
225- Some ( ( colon, path) )
226- } else {
227- None
228- } ,
229- fields : input. parse ( ) ?,
230- semi_token : input. parse ( ) ?,
231- } )
232- }
233- }
234-
235- fn generate_struct_definition ( _args : & StructArgs , target : & ItemRawStruct ) -> Result < TokenStream > {
239+ fn generate_struct_definition ( args : & StructArgs , target : & ItemStruct ) -> Result < TokenStream > {
236240 let attr_clone_copy = syn:: parse_quote! {
237241 #[ derive( Clone , Copy ) ]
238242 } ;
@@ -262,18 +266,26 @@ fn generate_struct_definition(_args: &StructArgs, target: &ItemRawStruct) -> Res
262266 } )
263267 . collect :: < Vec < _ > > ( ) ;
264268
269+ let memory = if let Some ( inherits) = & args. inherits {
270+ let mut inherits = inherits. clone ( ) ;
271+ self :: add_type_param ( & mut inherits, parse_quote ! ( #IDENT_MEMORY_VIEW_T ) ) ;
272+ quote ! { inner: #inherits }
273+ } else {
274+ quote ! { memory: #IDENT_MEMORY_VIEW_T }
275+ } ;
276+
265277 Ok ( quote ! {
266278 #( #attributes) *
267279 #vis struct #name #struct_generics {
268- memory : # IDENT_MEMORY_VIEW_T ,
280+ #memory ,
269281 _type: std:: marker:: PhantomData <( #( #type_list, ) * ) >,
270282 }
271283 } )
272284}
273285
274286pub fn raw_struct ( attr : TokenStream , input : TokenStream ) -> Result < TokenStream > {
275287 let args = syn:: parse2 :: < StructArgs > ( attr) ?;
276- let target = syn:: parse2 :: < ItemRawStruct > ( input) ?;
288+ let target = syn:: parse2 :: < ItemStruct > ( input) ?;
277289
278290 let struct_name = target. ident . clone ( ) ;
279291 let struct_name_str = format ! ( "{}" , target. ident) ;
@@ -295,6 +307,54 @@ pub fn raw_struct(attr: TokenStream, input: TokenStream) -> Result<TokenStream>
295307
296308 let struct_def = self :: generate_struct_definition ( & args, & target) ?;
297309
310+ let impl_impl = if let Some ( _inherits) = & args. inherits {
311+ quote ! {
312+ impl #impl_generics raw_struct:: ViewableImplementation <#IDENT_MEMORY_VIEW_T > for #struct_name #impl_ty_generics #impl_where_clause {
313+ fn memory_view( & self ) -> & #IDENT_MEMORY_VIEW_T {
314+ self . inner. memory_view( )
315+ }
316+
317+ fn into_memory_view( self ) -> #IDENT_MEMORY_VIEW_T {
318+ self . inner. into_memory_view( )
319+ }
320+ }
321+ }
322+ } else {
323+ quote ! {
324+ impl #impl_generics raw_struct:: ViewableImplementation <#IDENT_MEMORY_VIEW_T > for #struct_name #impl_ty_generics #impl_where_clause {
325+ fn memory_view( & self ) -> & #IDENT_MEMORY_VIEW_T {
326+ & self . memory
327+ }
328+
329+ fn into_memory_view( self ) -> #IDENT_MEMORY_VIEW_T {
330+ self . memory
331+ }
332+ }
333+ }
334+ } ;
335+
336+ let impl_construct_from_memory = if let Some ( inherits) = & args. inherits {
337+ quote ! { #struct_name { inner: #inherits :: from_memory( memory) , _type: Default :: default ( ) } }
338+ } else {
339+ quote ! { #struct_name { memory, _type: Default :: default ( ) } }
340+ } ;
341+
342+ let deref_impl = if let Some ( inherits) = & args. inherits {
343+ let mut inherits = inherits. clone ( ) ;
344+ self :: add_type_param ( & mut inherits, parse_quote ! ( #IDENT_MEMORY_VIEW_T ) ) ;
345+ Some ( quote ! {
346+ impl #impl_generics core:: ops:: Deref for #struct_name #impl_ty_generics #impl_where_clause {
347+ type Target = #inherits;
348+
349+ fn deref( & self ) -> & Self :: Target {
350+ & self . inner
351+ }
352+ }
353+ } )
354+ } else {
355+ None
356+ } ;
357+
298358 let sized_impl = if let Some ( memory) = args. memory {
299359 Some ( quote ! {
300360 impl #vanilla_impl_generics raw_struct:: SizedViewable for #struct_name #vanilla_ty_generics #vanilla_where_clause {
@@ -312,15 +372,7 @@ pub fn raw_struct(attr: TokenStream, input: TokenStream) -> Result<TokenStream>
312372 #accessors
313373 }
314374
315- impl #impl_generics raw_struct:: ViewableImplementation <#IDENT_MEMORY_VIEW_T > for #struct_name #impl_ty_generics #impl_where_clause {
316- fn memory_view( & self ) -> & #IDENT_MEMORY_VIEW_T {
317- & self . memory
318- }
319-
320- fn into_memory_view( self ) -> #IDENT_MEMORY_VIEW_T {
321- self . memory
322- }
323- }
375+ #impl_impl
324376
325377 impl #vanilla_impl_generics raw_struct:: Viewable for #struct_name #vanilla_ty_generics #vanilla_where_clause {
326378 type Implementation <#IDENT_MEMORY_VIEW_T : raw_struct:: MemoryView > = #struct_name #impl_ty_generics;
@@ -330,10 +382,12 @@ pub fn raw_struct(attr: TokenStream, input: TokenStream) -> Result<TokenStream>
330382 }
331383
332384 fn from_memory<#IDENT_MEMORY_VIEW_T : raw_struct:: MemoryView >( memory: #IDENT_MEMORY_VIEW_T ) -> Self :: Implementation <#IDENT_MEMORY_VIEW_T > {
333- #struct_name { memory , _type : Default :: default ( ) }
385+ #impl_construct_from_memory
334386 }
335387 }
336388
337389 #sized_impl
390+
391+ #deref_impl
338392 } )
339393}
0 commit comments