Skip to content

Commit 91e8054

Browse files
committed
Add support for #[row(crate = ...)]
1 parent 3e81b45 commit 91e8054

File tree

3 files changed

+53
-8
lines changed

3 files changed

+53
-8
lines changed

derive/src/lib.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,49 @@
11
use proc_macro2::TokenStream;
2-
use quote::quote;
2+
use quote::{quote, ToTokens};
33
use serde_derive_internals::{
44
attr::{Container, Default as SerdeDefault, Field},
55
Ctxt,
66
};
77
use 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+
947
fn 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))]
4078
pub 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
};

src/row.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,21 +75,21 @@ pub(crate) fn join_column_names<R: Row>() -> Option<String> {
7575

7676
#[cfg(test)]
7777
mod tests {
78-
// XXX: need for `derive(Row)`. Provide `row(crate = ..)` instead.
79-
use crate as clickhouse;
80-
use clickhouse::Row;
78+
use crate::Row;
8179

8280
use super::*;
8381

8482
#[test]
8583
fn it_grabs_simple_struct() {
8684
#[derive(Row)]
85+
#[row(crate = crate)]
8786
#[allow(dead_code)]
8887
struct Simple1 {
8988
one: u32,
9089
}
9190

9291
#[derive(Row)]
92+
#[row(crate = crate)]
9393
#[allow(dead_code)]
9494
struct Simple2 {
9595
one: u32,
@@ -103,6 +103,7 @@ mod tests {
103103
#[test]
104104
fn it_grabs_mix() {
105105
#[derive(Row)]
106+
#[row(crate = crate)]
106107
struct SomeRow {
107108
_a: u32,
108109
}
@@ -115,6 +116,7 @@ mod tests {
115116
use serde::Serialize;
116117

117118
#[derive(Row, Serialize)]
119+
#[row(crate = crate)]
118120
#[allow(dead_code)]
119121
struct TopLevel {
120122
#[serde(rename = "two")]
@@ -129,6 +131,7 @@ mod tests {
129131
use serde::Serialize;
130132

131133
#[derive(Row, Serialize)]
134+
#[row(crate = crate)]
132135
#[allow(dead_code)]
133136
struct TopLevel {
134137
one: u32,
@@ -144,6 +147,7 @@ mod tests {
144147
use serde::Deserialize;
145148

146149
#[derive(Row, Deserialize)]
150+
#[row(crate = crate)]
147151
#[allow(dead_code)]
148152
struct TopLevel {
149153
one: u32,
@@ -158,6 +162,7 @@ mod tests {
158162
fn it_rejects_other() {
159163
#[allow(dead_code)]
160164
#[derive(Row)]
165+
#[row(crate = crate)]
161166
struct NamedTuple(u32, u32);
162167

163168
assert_eq!(join_column_names::<u32>(), None);
@@ -170,6 +175,7 @@ mod tests {
170175
use serde::Serialize;
171176

172177
#[derive(Row, Serialize)]
178+
#[row(crate = crate)]
173179
#[allow(dead_code)]
174180
struct MyRow {
175181
r#type: u32,

src/sql/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,19 @@ impl SqlBuilder {
149149
mod tests {
150150
use super::*;
151151

152-
// XXX: need for `derive(Row)`. Provide `row(crate = ..)` instead.
153-
use crate as clickhouse;
154152
use clickhouse_derive::Row;
155153

156154
#[allow(unused)]
157155
#[derive(Row)]
156+
#[row(crate = crate)]
158157
struct Row {
159158
a: u32,
160159
b: u32,
161160
}
162161

163162
#[allow(unused)]
164163
#[derive(Row)]
164+
#[row(crate = crate)]
165165
struct Unnamed(u32, u32);
166166

167167
#[test]

0 commit comments

Comments
 (0)