Question: multiple ways to deserialize / date example
Opened this issue · 1 comments
What are some recommended ways to handle this situation?
Given this Date
struct:
pub struct Date {
pub year: u16,
pub month: u8,
pub day: u8,
}
I want to allow a person typing into a .ron
file to use the usual syntax or (2023, 9, 17)
corresponding to:
pub struct DateTuple(pub u16, pub u8, pub u8)
RON leans on Serde heavily, and I've started looking at ways to let Serde handle this.
I'm asking this question mostly as a jumping off point so that I can suggest some content for RON documentation and FAQs.
If you only want to support the (2023, 9, 17)
syntax, you could define the DateTuple
type as a private helper and forward the Serialize
and Deserialize
impls to it. You can either use serde's #[serde(from = DataTuple, into = DataTuple)]
attributes for that, or write an explicit impl that just calls the helper.
If you want to support both (2023, 9, 17)
and (year: 2023, month: 9, day: 17)
, you will need to use deserialize_any
. My strategy for this is to go to Rust playground and expand the auto-generated impls and to customise them (note that I have not cleaned up this code at all, though I would recommend doing that):
#[derive(serde::Serialize)]
pub struct Date {
pub year: u16,
pub month: u8,
pub day: u8,
}
#[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for Date {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __field1, __field2, }
#[doc(hidden)]
struct __FieldVisitor;
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private::Formatter)
-> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private::Ok(__Field::__field0),
1u64 => _serde::__private::Ok(__Field::__field1),
2u64 => _serde::__private::Ok(__Field::__field2),
_ =>
_serde::__private::Err(_serde::de::Error::invalid_value(_serde::de::Unexpected::Unsigned(__value),
&"field index 0 <= i < 3")),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"year" => _serde::__private::Ok(__Field::__field0),
"month" => _serde::__private::Ok(__Field::__field1),
"day" => _serde::__private::Ok(__Field::__field2),
_ => {
_serde::__private::Err(_serde::de::Error::unknown_field(__value,
FIELDS))
}
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"year" => _serde::__private::Ok(__Field::__field0),
b"month" => _serde::__private::Ok(__Field::__field1),
b"day" => _serde::__private::Ok(__Field::__field2),
_ => {
let __value = &_serde::__private::from_utf8_lossy(__value);
_serde::__private::Err(_serde::de::Error::unknown_field(__value,
FIELDS))
}
}
}
}
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private::PhantomData<Date>,
lifetime: _serde::__private::PhantomData<&'de ()>,
}
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = Date;
fn expecting(&self,
__formatter: &mut _serde::__private::Formatter)
-> _serde::__private::fmt::Result {
_serde::__private::Formatter::write_str(__formatter,
"struct Date")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private::Result<Self::Value, __A::Error> where
__A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<u16>(&mut __seq)?
{
_serde::__private::Some(__value) => __value,
_serde::__private::None =>
return _serde::__private::Err(_serde::de::Error::invalid_length(0usize,
&"struct Date with 3 elements")),
};
let __field1 =
match _serde::de::SeqAccess::next_element::<u8>(&mut __seq)?
{
_serde::__private::Some(__value) => __value,
_serde::__private::None =>
return _serde::__private::Err(_serde::de::Error::invalid_length(1usize,
&"struct Date with 3 elements")),
};
let __field2 =
match _serde::de::SeqAccess::next_element::<u8>(&mut __seq)?
{
_serde::__private::Some(__value) => __value,
_serde::__private::None =>
return _serde::__private::Err(_serde::de::Error::invalid_length(2usize,
&"struct Date with 3 elements")),
};
_serde::__private::Ok(Date {
year: __field0,
month: __field1,
day: __field2,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private::Result<Self::Value, __A::Error> where
__A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private::Option<u16> =
_serde::__private::None;
let mut __field1: _serde::__private::Option<u8> =
_serde::__private::None;
let mut __field2: _serde::__private::Option<u8> =
_serde::__private::None;
while let _serde::__private::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private::Option::is_some(&__field0) {
return _serde::__private::Err(<__A::Error as
_serde::de::Error>::duplicate_field("year"));
}
__field0 =
_serde::__private::Some(_serde::de::MapAccess::next_value::<u16>(&mut __map)?);
}
__Field::__field1 => {
if _serde::__private::Option::is_some(&__field1) {
return _serde::__private::Err(<__A::Error as
_serde::de::Error>::duplicate_field("month"));
}
__field1 =
_serde::__private::Some(_serde::de::MapAccess::next_value::<u8>(&mut __map)?);
}
__Field::__field2 => {
if _serde::__private::Option::is_some(&__field2) {
return _serde::__private::Err(<__A::Error as
_serde::de::Error>::duplicate_field("day"));
}
__field2 =
_serde::__private::Some(_serde::de::MapAccess::next_value::<u8>(&mut __map)?);
}
}
}
let __field0 =
match __field0 {
_serde::__private::Some(__field0) => __field0,
_serde::__private::None =>
_serde::__private::de::missing_field("year")?,
};
let __field1 =
match __field1 {
_serde::__private::Some(__field1) => __field1,
_serde::__private::None =>
_serde::__private::de::missing_field("month")?,
};
let __field2 =
match __field2 {
_serde::__private::Some(__field2) => __field2,
_serde::__private::None =>
_serde::__private::de::missing_field("day")?,
};
_serde::__private::Ok(Date {
year: __field0,
month: __field1,
day: __field2,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["year", "month", "day"];
// NOTE: switch from deserialize_struct to deserialize_any here
// _serde::Deserializer::deserialize_struct(__deserializer,
// "Date", FIELDS,
// __Visitor {
// marker: _serde::__private::PhantomData::<Date>,
// lifetime: _serde::__private::PhantomData,
// })
_serde::Deserializer::deserialize_any(__deserializer,
__Visitor {
marker: _serde::__private::PhantomData::<Date>,
lifetime: _serde::__private::PhantomData,
})
}
}
};