diff --git a/serde_derive/src/de.rs b/serde_derive/src/de.rs index 59b7e9f2..456773a8 100644 --- a/serde_derive/src/de.rs +++ b/serde_derive/src/de.rs @@ -1875,7 +1875,9 @@ fn deserialize_identifier( collect_other_fields: bool ) -> Fragment { let field_strs = fields.iter().map(|&(ref name, _)| name); + let field_borrowed_strs = fields.iter().map(|&(ref name, _)| name); let field_bytes = fields.iter().map(|&(ref name, _)| Literal::byte_string(name.as_bytes())); + let field_borrowed_bytes = fields.iter().map(|&(ref name, _)| Literal::byte_string(name.as_bytes())); let constructors: &Vec<_> = &fields .iter() @@ -1997,15 +1999,22 @@ fn deserialize_identifier( }) }; - let (value_as_str_content, value_as_bytes_content) = if !collect_other_fields { - (None, None) + let (value_as_str_content, value_as_borrowed_str_content, + value_as_bytes_content, value_as_borrowed_bytes_content) = if !collect_other_fields { + (None, None, None, None) } else { ( Some(quote! { let __value = _serde::private::de::Content::String(__value.to_string()); }), + Some(quote! { + let __value = _serde::private::de::Content::Str(__value); + }), Some(quote! { let __value = _serde::private::de::Content::ByteBuf(__value.to_vec()); + }), + Some(quote! { + let __value = _serde::private::de::Content::Bytes(__value); }) ) }; @@ -2043,6 +2052,35 @@ fn deserialize_identifier( } } + fn visit_borrowed_str<__E>(self, __value: &'de str) -> _serde::export::Result + where __E: _serde::de::Error + { + match __value { + #( + #field_borrowed_strs => _serde::export::Ok(#constructors), + )* + _ => { + #value_as_borrowed_str_content + #fallthrough_arm + } + } + } + + fn visit_borrowed_bytes<__E>(self, __value: &'de [u8]) -> _serde::export::Result + where __E: _serde::de::Error + { + match __value { + #( + #field_borrowed_bytes => _serde::export::Ok(#constructors), + )* + _ => { + #bytes_to_str + #value_as_borrowed_bytes_content + #fallthrough_arm + } + } + } + fn visit_bytes<__E>(self, __value: &[u8]) -> _serde::export::Result where __E: _serde::de::Error { diff --git a/test_suite/tests/test_annotations.rs b/test_suite/tests/test_annotations.rs index 531b4eec..9eccf697 100644 --- a/test_suite/tests/test_annotations.rs +++ b/test_suite/tests/test_annotations.rs @@ -1684,3 +1684,82 @@ fn test_non_string_keys() { ], ); } + +#[test] +fn test_lifetime_propagation_for_flatten() { + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct A { + #[serde(flatten)] + t: T, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct B<'a> { + #[serde(flatten, borrow)] + t: HashMap<&'a str, u32>, + } + + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct C<'a> { + #[serde(flatten, borrow)] + t: HashMap<&'a [u8], u32>, + } + + let mut owned_map = HashMap::new(); + owned_map.insert("x".to_string(), 42u32); + assert_tokens( + &A { t: owned_map }, + &[ + Token::Map { len: None }, + Token::Str("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + let mut borrowed_map = HashMap::new(); + borrowed_map.insert("x", 42u32); + assert_ser_tokens( + &B { t: borrowed_map.clone() }, + &[ + Token::Map { len: None }, + Token::BorrowedStr("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + assert_de_tokens( + &B { t: borrowed_map }, + &[ + Token::Map { len: None }, + Token::BorrowedStr("x"), + Token::U32(42), + Token::MapEnd, + ], + ); + + let mut borrowed_map = HashMap::new(); + borrowed_map.insert(&b"x"[..], 42u32); + assert_ser_tokens( + &C { t: borrowed_map.clone() }, + &[ + Token::Map { len: None }, + Token::Seq { len: Some(1) }, + Token::U8(120), + Token::SeqEnd, + Token::U32(42), + Token::MapEnd, + ], + ); + + assert_de_tokens( + &C { t: borrowed_map }, + &[ + Token::Map { len: None }, + Token::BorrowedBytes(b"x"), + Token::U32(42), + Token::MapEnd, + ], + ); +}