Feature request: enabling grammar typing for sequences via deserialize

Open
#578 4 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
rust
Domain
backend

Research direction

Start by reading the deserializer’s sequence handling, especially SeqItemDeserializer::deserialize_seq, and compare it with the serializer’s flattening behavior. The issue describes two changes: trying None for remaining tuple elements at sequence end and recursively flattening nested sequences; investigate the infinite-loop risk for vectors of Option and other design effects before proposing an approach. Done means the example round-trips while sequence termination and nested sequences behave safely.

Written by the indexing model from the issue text.

Description

enhancement serde

This issue is to gauge interest in being able to validate the variadic layout of a sequence via tuple elements that are Option

I have a use case to generate schema definitions with sequences defined by a grammar. Given that it's already possible to enforce order, and serializing has builtin flattening of options and sequences, there are two key features for deserializing missing that would fully enable building types to validate a sequence grammar.

Deserializing end of sequence for a tuple should try to deserialize as visiting None for each remaining element of the tuple sequence.

Deserializing a sequence of sequences (of sequences...*) should recursively flatten.

Both these features are already present implicitly in the serializer, this would just be making the deserializer match.

This would allow for examples like below to work

use quick_xml::{de::from_str, se::to_string};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum ABChoice {
    A,
    B,
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
enum CDChoice {
    C,
    D,
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct Root {
    #[serde(rename = "$value")]
    content: (Vec<ABChoice>, Vec<CDChoice>, Option<Vec<ABChoice>>),
}
let root = Root {
    content: (
        vec![ABChoice::A, ABChoice::B],
        vec![CDChoice::C],
        Some(vec![ABChoice::A]),
    ),
};
let serialized = to_string(&root).unwrap();
dbg!(&serialized);
let deserialized = from_str(&serialized).unwrap();
assert_eq!(root, deserialized);

Currently serializing this produces the string

<Root><A/><B/><C/><A/></Root>

Mirroring this in the deserializer is desirable.

I've managed to get a hacky implementation of this to work sending all cases that would stop iteration to first try and deserialize as the DeserializeSeed with a deserializer that can only call visit_none, however this would lead to the case where a vector of Options produces an infinite loop so there's still some design work to be done there.

With regards to recursive sequence flattening, I suspect the offender is <SeqItemDeserializer as de::Deserializer>::deserialize_seq, however just making this recursive seems to have other potential ramifications associated. As such, design input would be appreciated there as well.

I'm very happy to do the work myself. However, I would like to consult, firstly, if this would be something that can be upstreamed, and secondly if there are any pitfalls in this area I should be aware of from a design standpoint, particularly that would prevent it getting upstreamed.

Dominant language
Rust
Stars
1.6k
Forks
299
Avg merge
2d 4h
Merged PRs (30d)
9

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tafia/quick-xml

All issues in tafia/quick-xml

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.