ron-rs/ron

Question: multiple ways to deserialize / date example

Opened this issue · 1 comments

xpe commented

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,
                    })
            }
        }
    };