Skip to content

Commit a544538

Browse files
committed
more conformance fixes to oneof handling and nan/inf serialization
1 parent a52d4fc commit a544538

File tree

6 files changed

+71
-6
lines changed

6 files changed

+71
-6
lines changed

conformance/failing_tests.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ Recommended.FieldMaskTooManyUnderscore.JsonOutput
1414
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
1515
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
1616
Recommended.Proto3.JsonInput.NullValueInOtherOneofOldFormat.Validator
17+
18+
# These just aren't possible right now, because we can't represent unknown
19+
# enum values in the message struct (they are stored as i32).
20+
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
21+
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
22+
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput

prost-derive/src/serde/de.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,24 @@ pub fn impl_for_message(
124124
field_matches.push(quote! {
125125
__Field::#field_variant_ident(key) => {
126126
if _private::Option::is_some(&#field_variant_ident) {
127-
return _private::Err(
128-
<__A::Error as _serde::de::Error>::duplicate_field(#field_ident_str)
127+
let __val = _serde::de::MapAccess::next_value_seed(
128+
&mut __map,
129+
_private::DesIntoWithConfig::<_private::NullDeserializer, ()>::new(
130+
__config
131+
),
129132
);
133+
match __val {
134+
_private::Ok(()) => continue,
135+
_private::Err(_) => return _private::Err(
136+
<__A::Error as _serde::de::Error>::duplicate_field(#field_ident_str)
137+
),
138+
}
130139
}
131140
let __val = _serde::de::MapAccess::next_value_seed(
132141
&mut __map,
133142
_private::OneOfDeserializer(key, __config),
134143
)?;
135-
if __val.is_some() {
144+
if _private::Option::is_some(&__val) {
136145
#field_variant_ident = _private::Some(__val);
137146
}
138147
}

prost-types/src/serde.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,14 @@ impl CustomSerialize for Value {
290290
{
291291
match self.kind.as_ref() {
292292
Some(value::Kind::NullValue(_)) | None => serializer.serialize_none(),
293-
Some(value::Kind::NumberValue(val)) => serializer.serialize_f64(*val),
293+
Some(value::Kind::NumberValue(val)) => {
294+
if val.is_nan() || val.is_infinite() {
295+
return Err(serde::ser::Error::custom(format!(
296+
"serializing a value::Kind::NumberValue, which is {val}, is not possible"
297+
)));
298+
}
299+
serializer.serialize_f64(*val)
300+
}
294301
Some(value::Kind::StringValue(val)) => serializer.serialize_str(val),
295302
Some(value::Kind::BoolValue(val)) => serializer.serialize_bool(*val),
296303
Some(value::Kind::StructValue(val)) => {

prost/src/serde/de.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ pub use forward::ForwardDeserializer;
118118
pub use map::MapDeserializer;
119119
pub use message::MessageDeserializer;
120120
pub use oneof::{DeserializeOneOf, OneOfDeserializer};
121-
pub use option::OptionDeserializer;
121+
pub use option::{NullDeserializer, OptionDeserializer};
122122
pub use r#enum::{DeserializeEnum, EnumDeserializer};
123123
pub use scalar::{BoolDeserializer, FloatDeserializer, IntDeserializer};
124124
pub use vec::VecDeserializer;

prost/src/serde/de/option.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,46 @@ where
6262
true
6363
}
6464
}
65+
66+
pub struct NullDeserializer;
67+
68+
impl DeserializeInto<()> for NullDeserializer {
69+
#[inline]
70+
fn deserialize_into<'de, D: serde::Deserializer<'de>>(
71+
deserializer: D,
72+
_config: &DeserializerConfig,
73+
) -> Result<(), D::Error> {
74+
struct Visitor;
75+
76+
impl<'de> serde::de::Visitor<'de> for Visitor {
77+
type Value = ();
78+
79+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
80+
write!(formatter, "a null value")
81+
}
82+
83+
#[inline]
84+
fn visit_none<E>(self) -> Result<Self::Value, E>
85+
where
86+
E: serde::de::Error,
87+
{
88+
Ok(())
89+
}
90+
91+
#[inline]
92+
fn visit_unit<E>(self) -> Result<Self::Value, E>
93+
where
94+
E: serde::de::Error,
95+
{
96+
Ok(())
97+
}
98+
}
99+
100+
deserializer.deserialize_option(Visitor)
101+
}
102+
103+
#[inline]
104+
fn can_deserialize_null() -> bool {
105+
true
106+
}
107+
}

prost/src/serde/private.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ pub use super::de::{
3333
BoolDeserializer, BytesDeserializer, CustomDeserialize, DefaultDeserializer, DesIntoWithConfig,
3434
DesWithConfig, DeserializeEnum, DeserializeInto, DeserializeOneOf, EnumDeserializer,
3535
FloatDeserializer, ForwardDeserializer, IntDeserializer, MapDeserializer, MessageDeserializer,
36-
OneOfDeserializer, OptionDeserializer, VecDeserializer,
36+
NullDeserializer, OneOfDeserializer, OptionDeserializer, VecDeserializer,
3737
};

0 commit comments

Comments
 (0)