ron-rs / ron

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

[Feature] Deserializer: Set Default Numeric Type #520

Open bbb651 opened 10 months ago

bbb651 commented 10 months ago

Currently it's possible to specify type suffixes for integers and floats to control what type they serialize to, however, for types without a type suffix the normal behavior of using the smallest numeric type that fits the value. I would like a way to use a consistent default type for values that specify one, I thought of two ways of achieving that:

My use case is using ron as a text format for dbus varients. These are dynamically typed objects that store their types as part of their value, and it makes sense for my use case to default integers to u32 and floats to f64.

juntyr commented 10 months ago

I may need some clarification before I'm able to give you a good answer. During serialisation, we always serialise numeric values as-is, and the ron::ser::PrettyConfig::number_suffixes flag can be used to add the type suffix to these values, i.e. serialising a u32 would always produce v_u32 independent of the value v. At deserialise time, when we parse numeric values, we then check for these suffixes. If they do not exist, we indeed interpret the value as belonging to the smallest possible type. If they do, then that is the type we use. Finally, we tell the serde::de::Visitor via its visit_ty (e.g. visit_u32) method that we have seen a value of a specific numeric type. serde's Deserialize implementations for the primitives allow values to be cast to larger or smaller types as long as they are in their range. However, if the ron value had a type suffix and serde hints at us that it is expecting a different numeric value, we do raise an error.

If I understood you correctly, you want to customise the behaviour of how to parse numeric values when we don't have their suffix and are not sure what numeric type they should be, which is the case when using deserialize_any, which e.g. affects how ron::Value is parsed. Is that correct? Would it be possible to handle this at the Deserialize impl side instead, e.g. by having a wrapper that always tries to forward a visit_ty call to the smallest/largest possible one or that only accepts a specific one and errors otherwise?