mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-06-13 05:31:02 +00:00
Saving progress on naming convention conversion code to try new Inflector changes. #788
This commit is contained in:
@@ -13,7 +13,6 @@ include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE-APACHE", "LICENSE-
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
syn = { version = "0.11", default-features = false, features = ["parsing"] }
|
syn = { version = "0.11", default-features = false, features = ["parsing"] }
|
||||||
Inflector = "0.7.0"
|
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "serde-rs/serde" }
|
travis-ci = { repository = "serde-rs/serde" }
|
||||||
|
|||||||
@@ -49,15 +49,15 @@ impl<'a> Item<'a> {
|
|||||||
match body {
|
match body {
|
||||||
Body::Enum(ref mut variants) => {
|
Body::Enum(ref mut variants) => {
|
||||||
for ref mut variant in variants {
|
for ref mut variant in variants {
|
||||||
variant.attrs.rename_by_rule(attrs.rename_all());
|
variant.attrs.rename_by_rule(attrs.rename_all()).unwrap_or_else(|err| cx.error(err));
|
||||||
for ref mut field in &mut variant.fields {
|
for ref mut field in &mut variant.fields {
|
||||||
field.attrs.rename_by_rule(variant.attrs.rename_all());
|
field.attrs.rename_by_rule(variant.attrs.rename_all()).unwrap_or_else(|err| cx.error(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Body::Struct(_, ref mut fields) => {
|
Body::Struct(_, ref mut fields) => {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
field.attrs.rename_by_rule(attrs.rename_all());
|
field.attrs.rename_by_rule(attrs.rename_all()).unwrap_or_else(|err| cx.error(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ use Ctxt;
|
|||||||
use syn;
|
use syn;
|
||||||
use syn::MetaItem::{List, NameValue, Word};
|
use syn::MetaItem::{List, NameValue, Word};
|
||||||
use syn::NestedMetaItem::{Literal, MetaItem};
|
use syn::NestedMetaItem::{Literal, MetaItem};
|
||||||
use inflector::Inflector;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
// This module handles parsing of `#[serde(...)]` attributes. The entrypoints
|
||||||
@@ -104,15 +103,67 @@ pub enum RenameRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RenameRule {
|
impl RenameRule {
|
||||||
pub fn apply(&self, name: String) -> String {
|
pub fn apply_to_variant(&self, variant_name: String) -> Result<String, String> {
|
||||||
match *self {
|
if *self == RenameRule::None {
|
||||||
RenameRule::None => name,
|
return Ok(variant_name);
|
||||||
RenameRule::PascalCase => name.to_pascal_case(),
|
|
||||||
RenameRule::CamelCase => name.to_camel_case(),
|
|
||||||
RenameRule::SnakeCase => name.to_snake_case(),
|
|
||||||
RenameRule::ScreamingSnakeCase => name.to_screaming_snake_case(),
|
|
||||||
RenameRule::KebabCase => name.to_kebab_case(),
|
|
||||||
}
|
}
|
||||||
|
let mut chars = variant_name.chars();
|
||||||
|
let start = chars.next().unwrap();
|
||||||
|
if start.is_lowercase() {
|
||||||
|
return Err(format!("#[serde(rename_all = \"...\")] expects enum variants to be \
|
||||||
|
named in `PascalCase`."));
|
||||||
|
}
|
||||||
|
Ok(self.apply_to_words(chars.fold(vec![start.to_lowercase().collect()], |mut words, c| {
|
||||||
|
if c.is_uppercase() {
|
||||||
|
words.push(c.to_lowercase().collect());
|
||||||
|
} else {
|
||||||
|
words.last_mut().unwrap().push(c);
|
||||||
|
}
|
||||||
|
words
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_to_field(&self, field_name: String) -> Result<String, String> {
|
||||||
|
if *self == RenameRule::None {
|
||||||
|
return Ok(field_name);
|
||||||
|
}
|
||||||
|
if field_name != field_name.to_lowercase() {
|
||||||
|
return Err(format!("#[serde(rename_all = \"...\")] expects fields to be named in \
|
||||||
|
`snake_case`."));
|
||||||
|
}
|
||||||
|
Ok(self.apply_to_words(field_name.split('_').map(|s| s.to_string()).collect()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_to_words(&self, lowercased_words: Vec<String>) -> String {
|
||||||
|
match *self {
|
||||||
|
RenameRule::PascalCase => Self::capitalising_join(lowercased_words),
|
||||||
|
RenameRule::CamelCase => {
|
||||||
|
let mut iter = lowercased_words.into_iter();
|
||||||
|
let mut first = iter.next().unwrap();
|
||||||
|
first.push_str(Self::capitalising_join(iter.collect()).as_str());
|
||||||
|
first
|
||||||
|
}
|
||||||
|
RenameRule::SnakeCase => Self::delimiting_join(lowercased_words, "_"),
|
||||||
|
RenameRule::ScreamingSnakeCase => Self::delimiting_join(lowercased_words, "_").to_uppercase(),
|
||||||
|
RenameRule::KebabCase => Self::delimiting_join(lowercased_words, "-"),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delimiting_join(lowercased_words: Vec<String>, delimiter: &str) -> String {
|
||||||
|
lowercased_words.join(delimiter)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capitalising_join(lowercased_words: Vec<String>) -> String {
|
||||||
|
lowercased_words.into_iter().map(Self::capitalise).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn capitalise(lowercased_word: String) -> String {
|
||||||
|
let mut iter = lowercased_word.chars();
|
||||||
|
let mut first: String = iter.next().unwrap().to_uppercase().collect();
|
||||||
|
first.push_str(iter.collect::<String>().as_str());
|
||||||
|
first
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,13 +558,14 @@ impl Variant {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_by_rule(&mut self, rename_rule: &RenameRule) {
|
pub fn rename_by_rule(&mut self, rename_rule: &RenameRule) -> Result<(), String> {
|
||||||
if !self.ser_renamed {
|
if !self.ser_renamed {
|
||||||
self.name.serialize = rename_rule.apply(self.name.serialize.clone());
|
self.name.serialize = rename_rule.apply_to_variant(self.name.serialize.clone())?;
|
||||||
}
|
}
|
||||||
if !self.de_renamed {
|
if !self.de_renamed {
|
||||||
self.name.deserialize = rename_rule.apply(self.name.deserialize.clone());
|
self.name.deserialize = rename_rule.apply_to_variant(self.name.deserialize.clone())?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_all(&self) -> &RenameRule {
|
pub fn rename_all(&self) -> &RenameRule {
|
||||||
@@ -709,13 +761,14 @@ impl Field {
|
|||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename_by_rule(&mut self, rename_rule: &RenameRule) {
|
pub fn rename_by_rule(&mut self, rename_rule: &RenameRule) -> Result<(), String> {
|
||||||
if !self.ser_renamed {
|
if !self.ser_renamed {
|
||||||
self.name.serialize = rename_rule.apply(self.name.serialize.clone());
|
self.name.serialize = rename_rule.apply_to_field(self.name.serialize.clone())?;
|
||||||
}
|
}
|
||||||
if !self.de_renamed {
|
if !self.de_renamed {
|
||||||
self.name.deserialize = rename_rule.apply(self.name.deserialize.clone());
|
self.name.deserialize = rename_rule.apply_to_field(self.name.deserialize.clone())?;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn skip_serializing(&self) -> bool {
|
pub fn skip_serializing(&self) -> bool {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
extern crate syn;
|
extern crate syn;
|
||||||
extern crate inflector;
|
|
||||||
|
|
||||||
pub mod ast;
|
pub mod ast;
|
||||||
pub mod attr;
|
pub mod attr;
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
extern crate serde_codegen_internals;
|
||||||
|
|
||||||
|
use serde_codegen_internals::attr::RenameRule;
|
||||||
|
use RenameRule::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_rename_rule_variant_strs() {
|
||||||
|
let variants = vec!["Outcome", "VeryTastyVegetables", "A", "Z42", "bad_snake_case"];
|
||||||
|
let variants_renamed_expected = vec![
|
||||||
|
(PascalCase, vec![Ok("Outcome"), Ok("VeryTastyVegetables"), Ok("A"), Ok("Z42"), Err(())]),
|
||||||
|
(CamelCase, vec![Ok("outcome"), Ok("veryTastyVegetables"), Ok("a"), Ok("z42"), Err(())]),
|
||||||
|
(SnakeCase, vec![Ok("outcome"), Ok("very_tasty_vegetables"), Ok("a"), Ok("z42"), Err(())]),
|
||||||
|
(ScreamingSnakeCase, vec![Ok("OUTCOME"), Ok("VERY_TASTY_VEGETABLES"), Ok("A"), Ok("Z42"), Err(())]),
|
||||||
|
(KebabCase, vec![Ok("outcome"), Ok("very-tasty-vegetables"), Ok("a"), Ok("z42"), Err(())]),
|
||||||
|
];
|
||||||
|
|
||||||
|
for variant in variants.iter() {
|
||||||
|
assert_eq!(RenameRule::None.apply_to_variant(variant.to_string()), Ok(variant.to_string()));
|
||||||
|
}
|
||||||
|
for (rule, expected) in variants_renamed_expected.into_iter().map(|(rule, expected)| (rule, expected.into_iter().map(|expect| expect.map(|str| str.to_string())))) {
|
||||||
|
for (variant, expected) in variants.iter().zip(expected) {
|
||||||
|
assert_eq!(rule.apply_to_variant(variant.to_string()).map_err(|_| ()), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user