Skip to content

Commit

Permalink
Error instead of panic when deserializing non-identifier field name (#…
Browse files Browse the repository at this point in the history
…415)

* Error instead of panic when deserializing non-identifier field name

* Fix code coverage for tests

* Added CHANGELOG entry
  • Loading branch information
juntyr authored Oct 7, 2022
1 parent 7a68926 commit 2b9a50c
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix issue [#401](https://github.com/ron-rs/ron/issues/401) with correct raw struct name identifier parsing ([#402](https://github.com/ron-rs/ron/pull/402))
- Add `ron::value::RawValue` helper type which can (de)serialize any valid RON ([#407](https://github.com/ron-rs/ron/pull/407))
- Fix issue [#410](https://github.com/ron-rs/ron/issues/410) trailing comma parsing in tuples and `Some` ([#412](https://github.com/ron-rs/ron/pull/412))
- Error instead of panic when deserializing non-identifiers as field names ([#415](https://github.com/ron-rs/ron/pull/415))

## [0.8.0] - 2022-08-17

Expand Down
54 changes: 27 additions & 27 deletions src/de/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,177 +40,177 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> {
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_i8<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_i16<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_i32<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_i64<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

#[cfg(feature = "integer128")]
fn deserialize_i128<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_u8<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_u16<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_u32<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_u64<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

#[cfg(feature = "integer128")]
fn deserialize_u128<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_f32<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_f64<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_char<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_string<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_bytes<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_byte_buf<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_option<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_unit<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_unit_struct<V>(self, _: &'static str, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_newtype_struct<V>(self, _: &'static str, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_seq<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_tuple<V>(self, _: usize, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_tuple_struct<V>(self, _: &'static str, _: usize, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_map<V>(self, _: V) -> Result<V::Value>
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_struct<V>(
Expand All @@ -222,7 +222,7 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> {
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_enum<V>(
Expand All @@ -234,7 +234,7 @@ impl<'a, 'b: 'a, 'c> de::Deserializer<'b> for &'c mut IdDeserializer<'a, 'b> {
where
V: Visitor<'b>,
{
unimplemented!("IdDeserializer may only be used for identifiers")
Err(Error::ExpectedIdentifier)
}

fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
Expand Down
2 changes: 1 addition & 1 deletion src/value/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl RawValue {

/// Helper function to validate a RON string and turn it into a `RawValue`.
pub fn from_boxed_ron(ron: Box<str>) -> SpannedResult<Box<Self>> {
match Options::default().from_str::<&Self>(&*ron) {
match Options::default().from_str::<&Self>(&ron) {
Ok(_) => Ok(Self::from_boxed_str(ron)),
Err(err) => Err(err),
}
Expand Down
2 changes: 1 addition & 1 deletion tests/203_error_positions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ enum Test {
StructVariant { a: bool, b: NonZeroU32, c: i32 },
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq)] // GRCOV_EXCL_LINE
struct TypeError;

impl<'de> Deserialize<'de> for TypeError {
Expand Down
94 changes: 94 additions & 0 deletions tests/non_identifier_identifier.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
macro_rules! test_non_identifier {
($test_name:ident => $deserialize_method:ident($($deserialize_param:expr),*)) => {
#[test]
fn $test_name() {
use serde::{Deserialize, Deserializer, de::Visitor, de::MapAccess};

struct FieldVisitor;

impl<'de> Visitor<'de> for FieldVisitor {
type Value = FieldName;

// GRCOV_EXCL_START
fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.write_str("an error")
}
// GRCOV_EXCL_STOP
}

struct FieldName;

impl<'de> Deserialize<'de> for FieldName {
fn deserialize<D: Deserializer<'de>>(deserializer: D)
-> Result<Self, D::Error>
{
deserializer.$deserialize_method($($deserialize_param,)* FieldVisitor)
}
}

struct StructVisitor;

impl<'de> Visitor<'de> for StructVisitor {
type Value = Struct;

// GRCOV_EXCL_START
fn expecting(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.write_str("a struct")
}
// GRCOV_EXCL_STOP

fn visit_map<A: MapAccess<'de>>(self, mut map: A)
-> Result<Self::Value, A::Error>
{
map.next_key::<FieldName>().map(|_| Struct)
}
}

#[derive(Debug)]
struct Struct;

impl<'de> Deserialize<'de> for Struct {
fn deserialize<D: Deserializer<'de>>(deserializer: D)
-> Result<Self, D::Error>
{
deserializer.deserialize_struct("Struct", &[], StructVisitor)
}
}

assert_eq!(
ron::from_str::<Struct>("(true: 4)").unwrap_err().code,
ron::Error::ExpectedIdentifier
)
}
};
}

test_non_identifier! { test_bool => deserialize_bool() }
test_non_identifier! { test_i8 => deserialize_i8() }
test_non_identifier! { test_i16 => deserialize_i16() }
test_non_identifier! { test_i32 => deserialize_i32() }
test_non_identifier! { test_i64 => deserialize_i64() }
#[cfg(feature = "integer128")]
test_non_identifier! { test_i128 => deserialize_i128() }
test_non_identifier! { test_u8 => deserialize_u8() }
test_non_identifier! { test_u16 => deserialize_u16() }
test_non_identifier! { test_u32 => deserialize_u32() }
test_non_identifier! { test_u64 => deserialize_u64() }
#[cfg(feature = "integer128")]
test_non_identifier! { test_u128 => deserialize_u128() }
test_non_identifier! { test_f32 => deserialize_f32() }
test_non_identifier! { test_f64 => deserialize_f64() }
test_non_identifier! { test_char => deserialize_char() }
test_non_identifier! { test_string => deserialize_string() }
test_non_identifier! { test_bytes => deserialize_bytes() }
test_non_identifier! { test_byte_buf => deserialize_byte_buf() }
test_non_identifier! { test_option => deserialize_option() }
test_non_identifier! { test_unit => deserialize_unit() }
test_non_identifier! { test_unit_struct => deserialize_unit_struct("") }
test_non_identifier! { test_newtype_struct => deserialize_newtype_struct("") }
test_non_identifier! { test_seq => deserialize_seq() }
test_non_identifier! { test_tuple => deserialize_tuple(0) }
test_non_identifier! { test_tuple_struct => deserialize_tuple_struct("", 0) }
test_non_identifier! { test_map => deserialize_map() }
test_non_identifier! { test_struct => deserialize_struct("", &[]) }
test_non_identifier! { test_enum => deserialize_enum("", &[]) }

0 comments on commit 2b9a50c

Please sign in to comment.