Skip to content

Commit 2582cc3

Browse files
authored
Allow renaming struct fields (paritytech#209)
* Allow renaming struct fields * Handle `#[scale_info(rename = ...)]` with struct field * Clean up by replacing if-else block with match expression * Rebase on master to align with syn@2 * Add more checks to rename_field test * Update CHANGELOG.md
1 parent 885a920 commit 2582cc3

File tree

5 files changed

+65
-6
lines changed

5 files changed

+65
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
- Add `rename` attribute for renaming struct fields [(#209)](https://github.com/paritytech/scale-info/pull/209)
11+
812
## [2.11.6] - 2024-11-20
913

1014
- add `#[allow(deprecated)]` attribute to the generated code.

derive/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,12 @@ impl TypeInfoImpl {
184184
} else {
185185
quote!(ty)
186186
};
187-
let name = if let Some(ident) = ident {
188-
quote!(.name(::core::stringify!(#ident)))
189-
} else {
190-
quote!()
187+
let name = match utils::maybe_renamed(f) {
188+
Some(ident) => quote!(.name(#ident)),
189+
None => ident
190+
.as_ref()
191+
.map(|ident| quote!(.name(::core::stringify!(#ident))))
192+
.unwrap_or(quote!()),
191193
};
192194
quote!(
193195
.field(|f| f

derive/src/utils.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,29 @@ pub fn should_skip(attrs: &[Attribute]) -> bool {
9696
.is_some()
9797
}
9898

99+
/// Look for a `#[scale_info(rename = $str)]` outer attribute on the given `Field`.
100+
pub fn maybe_renamed(field: &syn::Field) -> Option<String> {
101+
let outer_attrs = field
102+
.attrs
103+
.iter()
104+
.filter(|attr| attr.style == AttrStyle::Outer);
105+
scale_info_meta_item(outer_attrs, |meta| {
106+
if let Meta::NameValue(ref nv) = meta {
107+
if nv.path.is_ident("rename") {
108+
if let Expr::Lit(ExprLit {
109+
lit: Lit::Str(ref v),
110+
..
111+
}) = nv.value
112+
{
113+
return Some(v.value());
114+
}
115+
}
116+
}
117+
118+
None
119+
})
120+
}
121+
99122
fn codec_meta_item<'a, F, R, I, M>(itr: I, pred: F) -> Option<R>
100123
where
101124
F: FnMut(M) -> Option<R> + Clone,
@@ -105,6 +128,15 @@ where
105128
find_meta_item("codec", itr, pred)
106129
}
107130

131+
fn scale_info_meta_item<'a, F, R, I, M>(itr: I, pred: F) -> Option<R>
132+
where
133+
F: FnMut(M) -> Option<R> + Clone,
134+
I: Iterator<Item = &'a Attribute>,
135+
M: Parse,
136+
{
137+
find_meta_item("scale_info", itr, pred)
138+
}
139+
108140
fn find_meta_item<'a, F, R, I, M>(kind: &str, mut itr: I, mut pred: F) -> Option<R>
109141
where
110142
F: FnMut(M) -> Option<R> + Clone,

test_suite/derive_tests_no_std/src/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// Copyright 2019-2020
2-
// Parity Technologies (UK) Ltd. Technologies (UK) Ltd.
1+
// Copyright 2019-2020 Parity Technologies (UK) Ltd.
32
//
43
// Licensed under the Apache License, Version 2.0 (the "License");
54
// you may not use this file except in compliance with the License.

test_suite/tests/derive.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,3 +907,25 @@ fn replace_segments_works() {
907907

908908
assert_type!(R, ty);
909909
}
910+
911+
#[test]
912+
fn rename_field() {
913+
#[allow(unused)]
914+
#[derive(TypeInfo)]
915+
pub struct S {
916+
#[scale_info(rename = "type")]
917+
r#type: bool,
918+
#[scale_info(rename = "bar")]
919+
foo: u8,
920+
baz: u16,
921+
}
922+
923+
let ty = Type::builder().path(Path::new("S", "derive")).composite(
924+
Fields::named()
925+
.field(|f| f.ty::<bool>().name("type").type_name("bool"))
926+
.field(|f| f.ty::<u8>().name("bar").type_name("u8"))
927+
.field(|f| f.ty::<u16>().name("baz").type_name("u16")),
928+
);
929+
930+
assert_type!(S, ty);
931+
}

0 commit comments

Comments
 (0)