Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor the renaming code #1429

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions serde_derive/src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1855,7 +1855,7 @@ fn deserialize_untagged_newtype_variant(
}

fn deserialize_generated_identifier(
fields: &[(String, Ident)],
fields: &[(&str, Ident)],
cattrs: &attr::Container,
is_variant: bool,
other_idx: Option<usize>,
Expand Down Expand Up @@ -2017,7 +2017,7 @@ fn deserialize_custom_identifier(

fn deserialize_identifier(
this: &TokenStream,
fields: &[(String, Ident)],
fields: &[(&str, Ident)],
is_variant: bool,
fallthrough: Option<TokenStream>,
collect_other_fields: bool,
Expand Down
127 changes: 81 additions & 46 deletions serde_derive/src/internals/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,73 @@ impl<'c> BoolAttr<'c> {
}
}

/// A struct to keep track of the original, serailized, and deserialized names
/// for a container.
pub struct Name {
serialize: String,
deserialize: String,
original: String,
serialize: Option<String>,
deserialize: Option<String>,
}

fn unraw(ident: &Ident) -> String {
ident.to_string().trim_left_matches("r#").to_owned()
}

impl Name {
pub fn new(original: String) -> Name {
Name {
original: original,
serialize: None,
deserialize: None,
}
}

/// Return the container name for the container when serializing.
pub fn serialize_name(&self) -> String {
self.serialize.clone()
pub fn serialize_name(&self) -> &str {
self.serialize.as_ref().unwrap_or_else(|| &self.original)
}

/// Return the container name for the container when deserializing.
pub fn deserialize_name(&self) -> String {
self.deserialize.clone()
pub fn deserialize_name(&self) -> &str {
self.deserialize.as_ref().unwrap_or_else(|| &self.original)
}

/// Rename the container for serialization.
pub fn set_serialize_name(&mut self, name: String) {
self.serialize = Some(name);
}

/// Rename the container for deserialization.
pub fn set_deserialize_name(&mut self, name: String) {
self.deserialize = Some(name);
}

/// Rename the container for both serialization and deserialization.
#[allow(dead_code)] // This is for the public api of serde_derive_internals.
pub fn set_name(&mut self, name: String) {
self.set_serialize_name(name.clone());
self.set_deserialize_name(name);
}

/// Returns true if the serialized form of this container has been renamed.
pub fn serialize_renamed(&self) -> bool {
self.serialize.is_some()
}

/// Returns true if the deserialized form of this container has been renamed.
pub fn deserialize_renamed(&self) -> bool {
self.deserialize.is_some()
}

/// Apply the specified rule to this name, if it hasn't been renamed already.
pub fn rename_by_rule<F>(&mut self, rule: F)
where F: Fn(&str) -> String {
if !self.serialize_renamed() {
self.serialize = Some(rule(&self.original));
}
if !self.deserialize_renamed() {
self.deserialize = Some(rule(&self.original));
}
}
}

Expand Down Expand Up @@ -382,11 +431,15 @@ impl Container {
}
}

let mut name = Name::new(unraw(&item.ident));
if let Some(ser) = ser_name.get() {
name.set_serialize_name(ser);
}
if let Some(de) = de_name.get() {
name.set_deserialize_name(de);
}
Container {
name: Name {
serialize: ser_name.get().unwrap_or_else(|| unraw(&item.ident)),
deserialize: de_name.get().unwrap_or_else(|| unraw(&item.ident)),
},
name: name,
transparent: transparent.get(),
deny_unknown_fields: deny_unknown_fields.get(),
default: default.get().unwrap_or(Default::None),
Expand Down Expand Up @@ -540,8 +593,6 @@ fn decide_identifier(
/// Represents variant attribute information
pub struct Variant {
name: Name,
ser_renamed: bool,
de_renamed: bool,
rename_all: RenameRule,
ser_bound: Option<Vec<syn::WherePredicate>>,
de_bound: Option<Vec<syn::WherePredicate>>,
Expand Down Expand Up @@ -695,17 +746,15 @@ impl Variant {
}
}

let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
let mut name = Name::new(unraw(&variant.ident));
if let Some(ser) = ser_name.get() {
name.set_serialize_name(ser);
}
if let Some(de) = de_name.get() {
name.set_deserialize_name(de);
}
Variant {
name: Name {
serialize: ser_name.unwrap_or_else(|| unraw(&variant.ident)),
deserialize: de_name.unwrap_or_else(|| unraw(&variant.ident)),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
name: name,
rename_all: rename_all.get().unwrap_or(RenameRule::None),
ser_bound: ser_bound.get(),
de_bound: de_bound.get(),
Expand All @@ -723,12 +772,7 @@ impl Variant {
}

pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_variant(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_variant(&self.name.deserialize);
}
self.name.rename_by_rule(|s| rule.apply_to_variant(s));
}

pub fn rename_all(&self) -> &RenameRule {
Expand Down Expand Up @@ -767,8 +811,6 @@ impl Variant {
/// Represents field attribute information
pub struct Field {
name: Name,
ser_renamed: bool,
de_renamed: bool,
skip_serializing: bool,
skip_deserializing: bool,
skip_serializing_if: Option<syn::ExprPath>,
Expand Down Expand Up @@ -1058,17 +1100,15 @@ impl Field {
collect_lifetimes(&field.ty, &mut borrowed_lifetimes);
}

let ser_name = ser_name.get();
let ser_renamed = ser_name.is_some();
let de_name = de_name.get();
let de_renamed = de_name.is_some();
let mut name = Name::new(ident);
if let Some(ser) = ser_name.get() {
name.set_serialize_name(ser);
}
if let Some(de) = de_name.get() {
name.set_deserialize_name(de);
}
Field {
name: Name {
serialize: ser_name.unwrap_or_else(|| ident.clone()),
deserialize: de_name.unwrap_or(ident),
},
ser_renamed: ser_renamed,
de_renamed: de_renamed,
name: name,
skip_serializing: skip_serializing.get(),
skip_deserializing: skip_deserializing.get(),
skip_serializing_if: skip_serializing_if.get(),
Expand All @@ -1089,12 +1129,7 @@ impl Field {
}

pub fn rename_by_rule(&mut self, rule: &RenameRule) {
if !self.ser_renamed {
self.name.serialize = rule.apply_to_field(&self.name.serialize);
}
if !self.de_renamed {
self.name.deserialize = rule.apply_to_field(&self.name.deserialize);
}
self.name.rename_by_rule(|s| rule.apply_to_field(s));
}

pub fn skip_serializing(&self) -> bool {
Expand Down
8 changes: 4 additions & 4 deletions serde_derive/src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,17 +525,17 @@ fn serialize_externally_tagged_variant(
}
Style::Tuple => serialize_tuple_variant(
TupleVariant::ExternallyTagged {
type_name: type_name,
type_name: type_name.to_string(),
variant_index: variant_index,
variant_name: variant_name,
variant_name: variant_name.to_string(),
},
params,
&variant.fields,
),
Style::Struct => serialize_struct_variant(
StructVariant::ExternallyTagged {
variant_index: variant_index,
variant_name: variant_name,
variant_name: variant_name.to_string(),
},
params,
&variant.fields,
Expand Down Expand Up @@ -601,7 +601,7 @@ fn serialize_internally_tagged_variant(
Style::Struct => serialize_struct_variant(
StructVariant::InternallyTagged {
tag: tag,
variant_name: variant_name,
variant_name: variant_name.to_string(),
},
params,
&variant.fields,
Expand Down