Skip to content

Commit

Permalink
Refactor the renaming code
Browse files Browse the repository at this point in the history
It's now concentrated in the Name struct. Some clones were avoided,
too.

Partly in preparation for serde-rs#1427
  • Loading branch information
Phlosioneer committed Nov 26, 2018
1 parent a043b2a commit 5f93edd
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 52 deletions.
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,
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,
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,
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,
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

0 comments on commit 5f93edd

Please sign in to comment.