-
Notifications
You must be signed in to change notification settings - Fork 123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Value::Struct variant and preserve struct names and formatting #328
base: master
Are you sure you want to change the base?
Conversation
Another hitch I haven't figured out yet is that the serde |
I suppose it's easy enough to adapt the |
Hmm ok actually a little more involved because of the recursion on the |
Ok I think I got it. Keeping |
Well, I got it working but since |
Struct names
80e938a
to
91fdaf1
Compare
Sorry, I've been punting on reviewing this. |
So I did get this to work and am using it in https://github.com/cswinter/pyron to (de)serialize Python dataclasses as ron, but there are still some issues with this that I'm not sure yet if they can be fixed. Both the The serialization implementation that allows preserving struct names/tuples is in better shape. It requires some amount of code duplication, and unfortunately needs an explicit call to a new |
For now, my main use case for this is https://github.com/cswinter/pyron, which doesn't use ron in a way that would run into the remaining issues. I would like to fix this properly at some point but still need to decide on the right approach and exactly what features I want so I'm planning to just let this stew for a while. The main approaches I'm considering:
If anyone has any other good ideas or opinions on how this should be approached I'd be glad to hear about them. |
I might be able to next week, feel free to ping me if I forget. |
Issue has had no activity in the last 60 days and is going to be closed in 7 days if no further activity occurs |
@torkleyy ping |
I've been thinking about a more AST-like Value type again and this is a sketch of what a pub enum NewValue<S: std::borrow::Borrow<str>> {
Unit,
Bool(bool),
Number(Number),
Char(char),
String(String),
Bytes(Vec<u8>),
List(Vec<NewValue<S>>),
Map(NewMap<S>),
NamedUnit {
name: S,
},
Newtype(Box<NewValue<S>>),
NamedNewtype {
name: S,
inner: Box<NewValue<S>>,
},
Tuple(Vec<NewValue<S>>),
NamedTuple {
name: S,
elems: Vec<NewValue<S>>,
},
Struct {
fields: FieldMap<S>,
},
NamedStruct {
name: S,
fields: FieldMap<S>,
}
}
#[cfg(not(feature = "indexmap"))]
type NewMap<S> = std::collections::BTreeMap<NewValue<S>, NewValue<S>>;
#[cfg(feature = "indexmap")]
type NewMap<S> = indexmap::IndexMap<NewValue<S>, NewValue<S>>;
#[cfg(not(feature = "indexmap"))]
type FieldMap<S> = std::collections::BTreeMap<S, NewValue<S>>;
#[cfg(feature = "indexmap")]
type FieldMap<S> = indexmap::IndexMap<S, NewValue<S>>; I think the biggest questions are:
|
Is there any progress made on this? I'd like to have lossless Value, which I can have multiple attempts at trying to deserialize from for untagged enums. Trying to make something like this work: #[derive(Debug, serde::Serialize, serde::Deserialize)]
enum A {
A1(String),
A2(String),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
enum B {
B1(String),
B2(String),
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(untagged)]
enum MyEnum {
A(A),
B(B),
}
let value = MyEnum::A(A::A1("Hello, world!".to_string()));
// valid RON serializations are:
// A1("")
// A2("")
// B1("")
// B2("")
// works fine with serde_json
let json = serde_json::to_string_pretty(&value).unwrap();
dbg!(serde_json::from_str::<MyEnum>(&json).unwrap());
// but doesn't work with ron
let ron = ron::ser::to_string_pretty(&value, ron::ser::PrettyConfig::default()).unwrap();
dbg!(ron::de::from_str::<MyEnum>(&ron).unwrap()); |
Not yet, unfortunately. Once I am back from parental leave, I will first tackle finally publishing v0.9, which includes a list of all the weird serde attribute cases that we currently cannot support because serde treats every format like JSON. If serde were to ever change that (and e.g. impl Trait in type aliases in traits makes that technically possible), an improved version of Ron’s Value type (as outlined above) would be used to fix most of these cases. While it will take me a few more months to get back to this PR, feel free to implement something similar to my idea sketched out above (essentially an AST-like Value type that allows round trips of RON [without serde attributes] but is more an AST than a Value enum since e.g. named structs and enum variants are ambiguous in RON when we are not given type information by the user). |
This change adds a
dreadful hackcreative workaround that allows us to distinguish between structs and maps during parsing and preserve struct names. It does so by abusing thesize_hint
method of theMapAccessor
as a side channel that exposes information about the struct name and whether we are visiting a struct or a map. I am somewhat confident that, within the context of the current implementation, this is sound and won't unexpectedly blow up in our face. TheCommaSeparated
struct with the unusualsize_hint
method is passed directly to theValueVisitor
and drained before we return control flow to any serde code, so anything else that might call thesize_hint
method will just receiveNone
values. I haven't confirmed this, but with some luck,size_hint
will also get inlined after monomorphization and optimized into something efficient.This makes progress towards #122, fixes #189, and fixes #264.
This change has been arrived at by sheer power of will rather than any kind of understanding of serde so there may be a better solution. There are still some smaller issues with the PR, before fixing those I first wanted to check whether this has any hope of getting merged.