11use proc_macro2:: TokenStream ;
2- use quote:: quote;
2+ use quote:: { quote, ToTokens } ;
33use serde_derive_internals:: {
44 attr:: { Container , Default as SerdeDefault , Field } ,
55 Ctxt ,
66} ;
77use syn:: { parse_macro_input, Data , DataStruct , DeriveInput , Fields } ;
88
9+ struct Attributes {
10+ crate_name : syn:: Path ,
11+ }
12+
13+ impl From < & [ syn:: Attribute ] > for Attributes {
14+ fn from ( attrs : & [ syn:: Attribute ] ) -> Self {
15+ const ATTRIBUTE_NAME : & str = "row" ;
16+ const ATTRIBUTE_SYNTAX : & str = "#[row(crate = ...)]" ;
17+
18+ const CRATE_NAME : & str = "crate" ;
19+ const DEFAULT_CRATE_NAME : & str = "clickhouse" ;
20+
21+ let mut crate_name = None ;
22+ for attr in attrs {
23+ if attr. path ( ) . is_ident ( ATTRIBUTE_NAME ) {
24+ let row = attr. parse_args :: < syn:: Expr > ( ) . unwrap ( ) ;
25+ let syn:: Expr :: Assign ( syn:: ExprAssign { left, right, .. } ) = row else {
26+ panic ! ( "expected `{}`" , ATTRIBUTE_SYNTAX ) ;
27+ } ;
28+ if left. to_token_stream ( ) . to_string ( ) != CRATE_NAME {
29+ panic ! ( "expected `{}`" , ATTRIBUTE_SYNTAX ) ;
30+ }
31+ let syn:: Expr :: Path ( syn:: ExprPath { path, .. } ) = * right else {
32+ panic ! ( "expected `{}`" , ATTRIBUTE_SYNTAX ) ;
33+ } ;
34+ crate_name = Some ( path) ;
35+ }
36+ }
37+ let crate_name = crate_name. unwrap_or_else ( || {
38+ syn:: Path :: from ( syn:: Ident :: new (
39+ DEFAULT_CRATE_NAME ,
40+ proc_macro2:: Span :: call_site ( ) ,
41+ ) )
42+ } ) ;
43+ Self { crate_name }
44+ }
45+ }
46+
947fn column_names ( data : & DataStruct , cx : & Ctxt , container : & Container ) -> TokenStream {
1048 match & data. fields {
1149 Fields :: Named ( fields) => {
@@ -36,11 +74,12 @@ fn column_names(data: &DataStruct, cx: &Ctxt, container: &Container) -> TokenStr
3674// TODO: support wrappers `Wrapper(Inner)` and `Wrapper<T>(T)`.
3775// TODO: support the `nested` attribute.
3876// TODO: support the `crate` attribute.
39- #[ proc_macro_derive( Row ) ]
77+ #[ proc_macro_derive( Row , attributes ( row ) ) ]
4078pub fn row ( input : proc_macro:: TokenStream ) -> proc_macro:: TokenStream {
4179 let input = parse_macro_input ! ( input as DeriveInput ) ;
4280
4381 let cx = Ctxt :: new ( ) ;
82+ let Attributes { crate_name } = Attributes :: from ( input. attrs . as_slice ( ) ) ;
4483 let container = Container :: from_ast ( & cx, & input) ;
4584 let name = input. ident ;
4685
@@ -56,7 +95,7 @@ pub fn row(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
5695
5796 let expanded = quote ! {
5897 #[ automatically_derived]
59- impl #impl_generics :: clickhouse :: Row for #name #ty_generics #where_clause {
98+ impl #impl_generics #crate_name :: Row for #name #ty_generics #where_clause {
6099 const COLUMN_NAMES : & ' static [ & ' static str ] = #column_names;
61100 }
62101 } ;
0 commit comments