ron-rs / ron

Rusty Object Notation
https://docs.rs/ron
Apache License 2.0
3.22k stars 118 forks source link

Question: multiple ways to deserialize / date example #507

Open xpe opened 10 months ago

xpe commented 10 months ago

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.

juntyr commented 10 months ago

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