Skip to content

Commit 9441a29

Browse files
authored
Merge pull request #2446 from Mingun/dedup2
Eliminate some duplicated code
2 parents 25381be + ab6588e commit 9441a29

File tree

2 files changed

+60
-123
lines changed

2 files changed

+60
-123
lines changed

serde/src/private/de.rs

+38-94
Original file line numberDiff line numberDiff line change
@@ -2738,11 +2738,7 @@ where
27382738
where
27392739
V: Visitor<'de>,
27402740
{
2741-
visitor.visit_map(FlatInternallyTaggedAccess {
2742-
iter: self.0.iter_mut(),
2743-
pending: None,
2744-
_marker: PhantomData,
2745-
})
2741+
self.deserialize_map(visitor)
27462742
}
27472743

27482744
fn deserialize_enum<V>(
@@ -2755,16 +2751,7 @@ where
27552751
V: Visitor<'de>,
27562752
{
27572753
for item in self.0.iter_mut() {
2758-
// items in the vector are nulled out when used. So we can only use
2759-
// an item if it's still filled in and if the field is one we care
2760-
// about.
2761-
let use_item = match *item {
2762-
None => false,
2763-
Some((ref c, _)) => c.as_str().map_or(false, |x| variants.contains(&x)),
2764-
};
2765-
2766-
if use_item {
2767-
let (key, value) = item.take().unwrap();
2754+
if let Some((key, value)) = use_item(item, variants) {
27682755
return visitor.visit_enum(EnumDeserializer::new(key, Some(value)));
27692756
}
27702757
}
@@ -2779,7 +2766,11 @@ where
27792766
where
27802767
V: Visitor<'de>,
27812768
{
2782-
visitor.visit_map(FlatMapAccess::new(self.0.iter()))
2769+
visitor.visit_map(FlatMapAccess {
2770+
iter: self.0.iter(),
2771+
pending_content: None,
2772+
_marker: PhantomData,
2773+
})
27832774
}
27842775

27852776
fn deserialize_struct<V>(
@@ -2791,7 +2782,12 @@ where
27912782
where
27922783
V: Visitor<'de>,
27932784
{
2794-
visitor.visit_map(FlatStructAccess::new(self.0.iter_mut(), fields))
2785+
visitor.visit_map(FlatStructAccess {
2786+
iter: self.0.iter_mut(),
2787+
pending_content: None,
2788+
fields: fields,
2789+
_marker: PhantomData,
2790+
})
27952791
}
27962792

27972793
fn deserialize_newtype_struct<V>(self, _name: &str, visitor: V) -> Result<V::Value, Self::Error>
@@ -2845,25 +2841,12 @@ where
28452841
}
28462842

28472843
#[cfg(any(feature = "std", feature = "alloc"))]
2848-
pub struct FlatMapAccess<'a, 'de: 'a, E> {
2844+
struct FlatMapAccess<'a, 'de: 'a, E> {
28492845
iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>,
28502846
pending_content: Option<&'a Content<'de>>,
28512847
_marker: PhantomData<E>,
28522848
}
28532849

2854-
#[cfg(any(feature = "std", feature = "alloc"))]
2855-
impl<'a, 'de, E> FlatMapAccess<'a, 'de, E> {
2856-
fn new(
2857-
iter: slice::Iter<'a, Option<(Content<'de>, Content<'de>)>>,
2858-
) -> FlatMapAccess<'a, 'de, E> {
2859-
FlatMapAccess {
2860-
iter: iter,
2861-
pending_content: None,
2862-
_marker: PhantomData,
2863-
}
2864-
}
2865-
}
2866-
28672850
#[cfg(any(feature = "std", feature = "alloc"))]
28682851
impl<'a, 'de, E> MapAccess<'de> for FlatMapAccess<'a, 'de, E>
28692852
where
@@ -2878,6 +2861,10 @@ where
28782861
for item in &mut self.iter {
28792862
// Items in the vector are nulled out when used by a struct.
28802863
if let Some((ref key, ref content)) = *item {
2864+
// Do not take(), instead borrow this entry. The internally tagged
2865+
// enum does its own buffering so we can't tell whether this entry
2866+
// is going to be consumed. Borrowing here leaves the entry
2867+
// available for later flattened fields.
28812868
self.pending_content = Some(content);
28822869
return seed.deserialize(ContentRefDeserializer::new(key)).map(Some);
28832870
}
@@ -2897,28 +2884,13 @@ where
28972884
}
28982885

28992886
#[cfg(any(feature = "std", feature = "alloc"))]
2900-
pub struct FlatStructAccess<'a, 'de: 'a, E> {
2887+
struct FlatStructAccess<'a, 'de: 'a, E> {
29012888
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
29022889
pending_content: Option<Content<'de>>,
29032890
fields: &'static [&'static str],
29042891
_marker: PhantomData<E>,
29052892
}
29062893

2907-
#[cfg(any(feature = "std", feature = "alloc"))]
2908-
impl<'a, 'de, E> FlatStructAccess<'a, 'de, E> {
2909-
fn new(
2910-
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
2911-
fields: &'static [&'static str],
2912-
) -> FlatStructAccess<'a, 'de, E> {
2913-
FlatStructAccess {
2914-
iter: iter,
2915-
pending_content: None,
2916-
fields: fields,
2917-
_marker: PhantomData,
2918-
}
2919-
}
2920-
}
2921-
29222894
#[cfg(any(feature = "std", feature = "alloc"))]
29232895
impl<'a, 'de, E> MapAccess<'de> for FlatStructAccess<'a, 'de, E>
29242896
where
@@ -2931,16 +2903,7 @@ where
29312903
T: DeserializeSeed<'de>,
29322904
{
29332905
while let Some(item) = self.iter.next() {
2934-
// items in the vector are nulled out when used. So we can only use
2935-
// an item if it's still filled in and if the field is one we care
2936-
// about. In case we do not know which fields we want, we take them all.
2937-
let use_item = match *item {
2938-
None => false,
2939-
Some((ref c, _)) => c.as_str().map_or(false, |key| self.fields.contains(&key)),
2940-
};
2941-
2942-
if use_item {
2943-
let (key, content) = item.take().unwrap();
2906+
if let Some((key, content)) = use_item(item, self.fields) {
29442907
self.pending_content = Some(content);
29452908
return seed.deserialize(ContentDeserializer::new(key)).map(Some);
29462909
}
@@ -2959,44 +2922,25 @@ where
29592922
}
29602923
}
29612924

2925+
/// Checks if first element of the specified pair matches one of the key from
2926+
/// `keys` parameter and if this is true, takes it from the option and returns.
2927+
/// Otherwise, or if `item` already empty, returns `None`.
29622928
#[cfg(any(feature = "std", feature = "alloc"))]
2963-
pub struct FlatInternallyTaggedAccess<'a, 'de: 'a, E> {
2964-
iter: slice::IterMut<'a, Option<(Content<'de>, Content<'de>)>>,
2965-
pending: Option<&'a Content<'de>>,
2966-
_marker: PhantomData<E>,
2967-
}
2968-
2969-
#[cfg(any(feature = "std", feature = "alloc"))]
2970-
impl<'a, 'de, E> MapAccess<'de> for FlatInternallyTaggedAccess<'a, 'de, E>
2971-
where
2972-
E: Error,
2973-
{
2974-
type Error = E;
2975-
2976-
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
2977-
where
2978-
T: DeserializeSeed<'de>,
2979-
{
2980-
for item in &mut self.iter {
2981-
if let Some((ref key, ref content)) = *item {
2982-
// Do not take(), instead borrow this entry. The internally tagged
2983-
// enum does its own buffering so we can't tell whether this entry
2984-
// is going to be consumed. Borrowing here leaves the entry
2985-
// available for later flattened fields.
2986-
self.pending = Some(content);
2987-
return seed.deserialize(ContentRefDeserializer::new(key)).map(Some);
2988-
}
2989-
}
2990-
Ok(None)
2991-
}
2929+
fn use_item<'de>(
2930+
item: &mut Option<(Content<'de>, Content<'de>)>,
2931+
keys: &[&str],
2932+
) -> Option<(Content<'de>, Content<'de>)> {
2933+
// items in the vector are nulled out when used. So we can only use
2934+
// an item if it's still filled in and if the field is one we care
2935+
// about.
2936+
let use_item = match *item {
2937+
None => false,
2938+
Some((ref c, _)) => c.as_str().map_or(false, |key| keys.contains(&key)),
2939+
};
29922940

2993-
fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
2994-
where
2995-
T: DeserializeSeed<'de>,
2996-
{
2997-
match self.pending.take() {
2998-
Some(value) => seed.deserialize(ContentRefDeserializer::new(value)),
2999-
None => panic!("value is missing"),
3000-
}
2941+
if use_item {
2942+
item.take()
2943+
} else {
2944+
None
30012945
}
30022946
}

serde_derive/src/de.rs

+22-29
Original file line numberDiff line numberDiff line change
@@ -3084,23 +3084,29 @@ struct DeTypeGenerics<'a>(&'a Parameters);
30843084
#[cfg(feature = "deserialize_in_place")]
30853085
struct InPlaceTypeGenerics<'a>(&'a Parameters);
30863086

3087+
/// If `'de` lifetime is defined, prepends it to list of generics
3088+
/// and then produces tokens for declaration generics on type
3089+
fn to_tokens(mut generics: syn::Generics, borrowed: &BorrowedLifetimes, tokens: &mut TokenStream) {
3090+
if borrowed.de_lifetime_param().is_some() {
3091+
let def = syn::LifetimeParam {
3092+
attrs: Vec::new(),
3093+
lifetime: syn::Lifetime::new("'de", Span::call_site()),
3094+
colon_token: None,
3095+
bounds: Punctuated::new(),
3096+
};
3097+
// Prepend 'de lifetime to list of generics
3098+
generics.params = Some(syn::GenericParam::Lifetime(def))
3099+
.into_iter()
3100+
.chain(generics.params)
3101+
.collect();
3102+
}
3103+
let (_, ty_generics, _) = generics.split_for_impl();
3104+
ty_generics.to_tokens(tokens);
3105+
}
3106+
30873107
impl<'a> ToTokens for DeTypeGenerics<'a> {
30883108
fn to_tokens(&self, tokens: &mut TokenStream) {
3089-
let mut generics = self.0.generics.clone();
3090-
if self.0.borrowed.de_lifetime_param().is_some() {
3091-
let def = syn::LifetimeParam {
3092-
attrs: Vec::new(),
3093-
lifetime: syn::Lifetime::new("'de", Span::call_site()),
3094-
colon_token: None,
3095-
bounds: Punctuated::new(),
3096-
};
3097-
generics.params = Some(syn::GenericParam::Lifetime(def))
3098-
.into_iter()
3099-
.chain(generics.params)
3100-
.collect();
3101-
}
3102-
let (_, ty_generics, _) = generics.split_for_impl();
3103-
ty_generics.to_tokens(tokens);
3109+
to_tokens(self.0.generics.clone(), &self.0.borrowed, tokens);
31043110
}
31053111
}
31063112

@@ -3113,20 +3119,7 @@ impl<'a> ToTokens for InPlaceTypeGenerics<'a> {
31133119
.chain(generics.params)
31143120
.collect();
31153121

3116-
if self.0.borrowed.de_lifetime_param().is_some() {
3117-
let def = syn::LifetimeParam {
3118-
attrs: Vec::new(),
3119-
lifetime: syn::Lifetime::new("'de", Span::call_site()),
3120-
colon_token: None,
3121-
bounds: Punctuated::new(),
3122-
};
3123-
generics.params = Some(syn::GenericParam::Lifetime(def))
3124-
.into_iter()
3125-
.chain(generics.params)
3126-
.collect();
3127-
}
3128-
let (_, ty_generics, _) = generics.split_for_impl();
3129-
ty_generics.to_tokens(tokens);
3122+
to_tokens(generics, &self.0.borrowed, tokens);
31303123
}
31313124
}
31323125

0 commit comments

Comments
 (0)