@@ -8,6 +8,7 @@ use syn::{
88 Parse ,
99 ParseStream ,
1010 } ,
11+ parse_quote,
1112 punctuated:: Punctuated ,
1213 spanned:: Spanned ,
1314 Attribute ,
@@ -22,6 +23,8 @@ use syn::{
2223 Lit ,
2324 LitStr ,
2425 MetaNameValue ,
26+ Path ,
27+ PathArguments ,
2528 Result ,
2629 Token ,
2730 TypeGenerics ,
@@ -209,6 +212,7 @@ struct ViewableGenerator<'a> {
209212 args : StructArgs ,
210213
211214 attributes : Vec < & ' a Attribute > ,
215+ inherits : Vec < Path > ,
212216 fields : Vec < ViewableField < ' a > > ,
213217
214218 generics_impl : ImplGenerics < ' a > ,
@@ -236,26 +240,37 @@ impl<'a> ViewableGenerator<'a> {
236240 }
237241 }
238242
239- fn parse_attributes ( target : & ' a ItemStruct ) -> Result < Vec < & ' a Attribute > > {
240- target
241- . attrs
242- . iter ( )
243- . map ( |attr| {
244- if attr. path . is_ident ( "doc" ) {
245- Ok ( attr)
246- } else {
247- Err ( Error :: new (
243+ fn parse_attributes ( target : & ' a ItemStruct ) -> Result < ( Vec < & ' a Attribute > , Vec < Path > ) > {
244+ let mut attributes = Vec :: with_capacity ( target. attrs . len ( ) ) ;
245+ let mut inherits = None ;
246+
247+ for attr in & target. attrs {
248+ if attr. path . is_ident ( "doc" ) {
249+ attributes. push ( attr) ;
250+ } else if attr. path . is_ident ( "inherits" ) {
251+ if inherits. is_some ( ) {
252+ return Err ( Error :: new (
248253 attr. span ( ) ,
249- "only \" doc \" attributes are supported on raw_structs " ,
250- ) )
254+ "only one instance of the \" inherits \" attributes is supported" ,
255+ ) ) ;
251256 }
252- } )
253- . collect :: < Result < Vec < _ > > > ( )
257+
258+ let args = attr. parse_args_with ( Punctuated :: < Path , Token ! [ , ] > :: parse_terminated) ?;
259+ inherits = Some ( args. iter ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ) ;
260+ } else {
261+ return Err ( Error :: new (
262+ attr. span ( ) ,
263+ "only \" doc\" or \" inherits\" attributes are supported on raw_structs" ,
264+ ) ) ;
265+ }
266+ }
267+
268+ Ok ( ( attributes, inherits. unwrap_or_default ( ) ) )
254269 }
255270
256271 fn new ( target : & ' a ItemStruct , target_args : StructArgs ) -> Result < Self > {
257272 let fields = Self :: parse_fields ( & target) ?;
258- let attributes = Self :: parse_attributes ( & target) ?;
273+ let ( attributes, inherits ) = Self :: parse_attributes ( & target) ?;
259274
260275 let ( generics_impl, generics_type, generics_where) = target. generics . split_for_impl ( ) ;
261276
@@ -285,6 +300,7 @@ impl<'a> ViewableGenerator<'a> {
285300 args : target_args,
286301
287302 attributes,
303+ inherits,
288304 fields,
289305
290306 generics_impl,
@@ -410,6 +426,36 @@ impl<'a> ViewableGenerator<'a> {
410426 for #instance_name<A , MemoryView > { }
411427 }
412428 }
429+
430+ fn generate_inheritances ( & self ) -> TokenStream {
431+ let accessor_name = & self . accessor_name ;
432+ let ( accessor_impl_generics, accessor_ty_generics, accessor_where_clause) =
433+ self . accessor_generics . split_for_impl ( ) ;
434+
435+ let mut inheritances = Vec :: with_capacity ( self . inherits . len ( ) ) ;
436+ for path in & self . inherits {
437+ let mut path = path. clone ( ) ;
438+ let Some ( last) = path. segments . last_mut ( ) else {
439+ panic ! ( "expected a path to have at least one segment" ) ;
440+ } ;
441+
442+ last. ident = Ident :: new ( & format ! ( "{}_Accessor" , last. ident) , last. span ( ) ) ;
443+ last. arguments = match & last. arguments {
444+ PathArguments :: None => PathArguments :: AngleBracketed ( parse_quote ! { <MemoryView > } ) ,
445+ PathArguments :: Parenthesized ( _) => unreachable ! ( ) ,
446+ PathArguments :: AngleBracketed ( value) => {
447+ let args = value. args . iter ( ) ;
448+ PathArguments :: AngleBracketed ( parse_quote ! { <MemoryView , #( #args, ) * > } )
449+ }
450+ } ;
451+
452+ inheritances. push ( quote ! {
453+ impl #accessor_impl_generics #path for dyn #accessor_name #accessor_ty_generics #accessor_where_clause { }
454+ } ) ;
455+ }
456+
457+ quote ! { #( #inheritances) * }
458+ }
413459}
414460
415461pub fn raw_struct ( attr : TokenStream , input : TokenStream ) -> Result < TokenStream > {
@@ -432,12 +478,19 @@ pub fn raw_struct(attr: TokenStream, input: TokenStream) -> Result<TokenStream>
432478 // generator.generate_instance_struct().to_string()
433479 // );
434480
481+ // println!(
482+ // "/* Inheritances: */ {}",
483+ // generator.generate_inheritances().to_string()
484+ // );
485+
435486 let main_trait = generator. generate_main_trait ( ) ;
436487 let accessors = generator. generate_accessor_trait ( ) ;
437488 let instance = generator. generate_instance_struct ( ) ;
489+ let inheritances = generator. generate_inheritances ( ) ;
438490 Ok ( quote ! {
439491 #main_trait
440492 #accessors
441493 #instance
494+ #inheritances
442495 } )
443496}
0 commit comments