Skip to content
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

Fix serde 1.0.181 compatibility #669

Merged
merged 15 commits into from
Oct 20, 2023
Merged

Conversation

Mingun
Copy link
Collaborator

@Mingun Mingun commented Oct 17, 2023

This PR reworks our mapping of enums to XML. Actually, it is more correct, because examples in our documentation was not checked and not worked.

Summary of changes

Rules:

  • In $value field the representation is always the same as top-level representation;
  • In $text field the representation is always the same as in normal field, but surrounding tags with field name are removed;
  • In normal field the representation is always contains a tag with field name

In $text fields enums represented as xs:simpleType

In tables below the following type is used when I say about normal, $text or $value fields:

struct Container {
  field: Enum,

  #[serde(rename = "$text")]
  text: Enum,

  #[serde(rename = "$value")]
  value: Enum,
}

Normal enum variant

Old

Before this PR the representation was:

Kind Top-level, in normal and $value fields In $text field
Unit <Unit/> (empty)
Newtype <Newtype>42</Newtype> 42
Tuple <Tuple>42</Tuple><Tuple>answer</Tuple> 42 answer
Struct <Struct><q>42</q><a>answer</a></Struct> Err(Unsupported)

New

In this PR the representation changed to:

Kind Top-level and in $value field In normal field In $text field
Unit <Unit/> <field>Unit</field> Unit
Newtype <Newtype>42</Newtype> Err(Unsupported) Err(Unsupported)
Tuple <Tuple>42</Tuple><Tuple>answer</Tuple> Err(Unsupported) Err(Unsupported)
Struct <Struct><q>42</q><a>answer</a></Struct> Err(Unsupported) Err(Unsupported)

$text enum variant

<field> in top-level serialization is the name of top-level element, serialization is impossible if it is not defined in the serializer.

Old

Before this PR the representation was:

Kind In normal field In $text and $value fields
Unit <field/> (empty)
Newtype <field>42</field> 42
Tuple <field>42 answer</field> 42 answer
Struct Err(Unsupported) Err(Unsupported)

New

In this PR the representation changed to:

Kind Top-level and in $value field In normal field In $text field
Unit (empty) <field/> (empty)
Newtype 42 Err(Unsupported)1 Err(Unsupported)2
Tuple 42 answer Err(Unsupported)3 Err(Unsupported)4
Struct Err(Unsupported) Err(Unsupported) Err(Unsupported)

Closes #630

I think, this will be the last merged PR for this release cycle, because it seems that no one will be reviewed to the end of week. I plan to release 0.31.0 on weekend.

Footnotes

  1. If this serialize as <field>42</field> then it will be ambiguity during deserialization, because it clash with Unit representation in normal field

  2. If this serialize as 42 then it will be ambiguity during deserialization, because it clash with Unit representation in $text field

  3. If this serialize as <field>42 answer</field> then it will be ambiguity during deserialization, because it clash with Unit representation in normal field

  4. If this serialize as 42 answer then it will be ambiguity during deserialization, because it clash with Unit representation in $text field

Mingun and others added 15 commits October 17, 2023 22:12
…e_*_variant`s

The code was simply copied with adaptation of parameter names.

This is required, because we want to change representation of internal `enum` fields
to match the current `$text` representation, but keep representation of top-level
enums unchanged (because there are no field for them that could be renamed to `$value`)

That means that

  enum Enum {
    Unit,
  }

would be represented differently when used as a top-level type or as a type of field:

<!-- top-level representation -->
<Unit/>

<!-- in-field representation (in field with name "field") -->
<field>Unit</field>

We need to change default in-field representation to be compatible with serde changes
since >=1.0.181. To get the old representation we need to rename the field to `$value`.
Actually, this is even more correct way, because I noticed, that currently serializer
and deserializer worked differently and a `de` module documentation contains an error,
which was unnoticed, because that code snippet is not tested. That will be fixed in next
commits.
This commit simply moves pieces of code from one place to another
After inlining we could notice that some unnecessary work are done.
This commit slightly changes the behavior, because construction of
XmlName checks the allowed names to be correspond to XML 1.1 rules
for names. This is not a problem, because we do not want to check
names that will not be used in the generated XML.
That way actual types will be shown in the documentation.
The new names more precisely reflects their purpose
…o ContentSerializer tests

In the next commits representation of enums will change and ElementSerializer won't
anymore support serialization of enum struct variants. In order to not lost tests
move them into ContentSerializer. It is also not meaningless (for `$value`), since it is
ContentSerializer which is responsible for serializing `$value` fields and struct
variants will be possible to serialize only in `$value` fields, i. e. they will be
serialized by ContentSerializer. For the `$text` fields tests is moved only to keep them.
Actually, our documentation was incorrect because test is failing.
All other commits in this branch will have a goal to fix that.

failures:
    src\de\mod.rs - de (line 1434)
…erent kind of fields

failures (10):
    without_root::enum_::externally_tagged::text_variant::normal_field::newtype
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple_with_spaces
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::text_field::unit
    without_root::enum_::externally_tagged::text_variant::value_field::newtype
    without_root::enum_::externally_tagged::text_variant::value_field::struct_
    without_root::enum_::externally_tagged::text_variant::value_field::tuple
    without_root::enum_::externally_tagged::text_variant::value_field::tuple_with_spaces
    without_root::enum_::externally_tagged::text_variant::value_field::unit
…ontentSerializer

ContentSerializer is used to write inner values of tags;
the `$value` name disables writing surrounding tags from fields.

(review with "ignore whitespace changes" option on)

failures (5):
    without_root::enum_::externally_tagged::text_variant::normal_field::newtype
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple_with_spaces
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::text_field::unit

Fixed (5):
    without_root::enum_::externally_tagged::text_variant::value_field::newtype
    without_root::enum_::externally_tagged::text_variant::value_field::struct_
    without_root::enum_::externally_tagged::text_variant::value_field::tuple
    without_root::enum_::externally_tagged::text_variant::value_field::tuple_with_spaces
    without_root::enum_::externally_tagged::text_variant::value_field::unit
New representation policy is compatible with serde>=1.0.181 and also more correct
and consistent with general mapping rules.

General rules of new policy:
- In `$value` field the representation is always the same as top-level representation;
- In `$text` field the representation is always the same as in normal field, but surrounding tags with field name are removed;
- In normal field the representation is always contains a tag with field name.

The tables below summarizes the representation policy. For examples in fields only content
at place of `...` is shown:
```
<Container>...</Container>
```

The struct which contains field looks like:
```
struct Container {
  field: Enum,

  #[serde(rename = "$text")]
  text: Enum,

  #[serde(rename = "$value")]
  value: Enum,
}
```

Normal enum variant
-------------------

### Old (before this commit) representation
|Kind   |Top-level, in normal and `$value` fields |In `$text` field|
|-------|-----------------------------------------|----------------|
|Unit   |`<Unit/>`                                |_(empty)_       |
|Newtype|`<Newtype>42</Newtype>`                  |`42`            |
|Tuple  |`<Tuple>42</Tuple><Tuple>answer</Tuple>` |`42 answer`     |
|Struct |`<Struct><q>42</q><a>answer</a></Struct>`|Err(Unsupported)|

### New (since this commit)
|Kind   |Top-level and in `$value` field          |In normal field      |In `$text` field|
|-------|-----------------------------------------|---------------------|----------------|
|Unit   |`<Unit/>`                                |`<field>Unit</field>`|`Unit`          |
|Newtype|`<Newtype>42</Newtype>`                  |Err(Unsupported)     |Err(Unsupported)|
|Tuple  |`<Tuple>42</Tuple><Tuple>answer</Tuple>` |Err(Unsupported)     |Err(Unsupported)|
|Struct |`<Struct><q>42</q><a>answer</a></Struct>`|Err(Unsupported)     |Err(Unsupported)|

`$text` enum variant
--------------------

`<field>` in top-level serialization is the name of top-level element, serialization is impossible if it is not defined in the serializer.

### Old (before this commit) representation
|Kind   |In `$value` field              |In normal field           |In `$text` field|
|-------|-------------------------------|--------------------------|----------------|
|Unit   |_(empty)_                      |`<field/>`                |_(empty)_       |
|Newtype|`42`                           |`<field>42</field>`       |`42`            |
|Tuple  |`42 answer`                    |`<field>42 answer</field>`|`42 answer`     |
|Struct |Err(Unsupported)               |Err(Unsupported)          |Err(Unsupported)|

### New (since this commit)
|Kind   |Top-level and in `$value` field|In normal field           |In `$text` field|
|-------|-------------------------------|--------------------------|----------------|
|Unit   |_(empty)_                      |`<field/>`                |_(empty)_       |
|Newtype|`42`                           |Err(Unsupported)          |Err(Unsupported)|
|Tuple  |`42 answer`                    |Err(Unsupported)          |Err(Unsupported)|
|Struct |Err(Unsupported)               |Err(Unsupported)          |Err(Unsupported)|

failures (28):
  --lib (14)
    se::element::tests::expand_empty_elements::enum_unit
    se::element::tests::expand_empty_elements::enum_unit_escaped
    se::element::tests::with_indent::attributes::enum_
    se::element::tests::with_indent::enum_newtype
    se::element::tests::with_indent::enum_struct
    se::element::tests::with_indent::enum_tuple
    se::element::tests::with_indent::enum_unit
    se::element::tests::with_indent::enum_unit_escaped
    se::element::tests::without_indent::attributes::enum_
    se::element::tests::without_indent::enum_newtype
    se::element::tests::without_indent::enum_struct
    se::element::tests::without_indent::enum_tuple
    se::element::tests::without_indent::enum_unit
    se::element::tests::without_indent::enum_unit_escaped
  serde-se (14):
    without_root::enum_::externally_tagged::normal_field2::empty_struct
    without_root::enum_::externally_tagged::normal_field2::newtype
    without_root::enum_::externally_tagged::normal_field2::struct_
    without_root::enum_::externally_tagged::normal_field2::tuple
    without_root::enum_::externally_tagged::normal_field2::unit
    without_root::enum_::externally_tagged::normal_field::empty_struct
    without_root::enum_::externally_tagged::normal_field::newtype
    without_root::enum_::externally_tagged::normal_field::struct_
    without_root::enum_::externally_tagged::normal_field::tuple
    without_root::enum_::externally_tagged::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::normal_field::newtype
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::text_field::unit
Now only unit variants can be serialized, all other returns error

failures (4):
    without_root::enum_::externally_tagged::normal_field2::unit
    without_root::enum_::externally_tagged::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::text_field::unit

Fixed (24):
  --lib (14, all)
    se::element::tests::expand_empty_elements::enum_unit
    se::element::tests::expand_empty_elements::enum_unit_escaped
    se::element::tests::with_indent::attributes::enum_
    se::element::tests::with_indent::enum_newtype
    se::element::tests::with_indent::enum_struct
    se::element::tests::with_indent::enum_tuple
    se::element::tests::with_indent::enum_unit
    se::element::tests::with_indent::enum_unit_escaped
    se::element::tests::without_indent::attributes::enum_
    se::element::tests::without_indent::enum_newtype
    se::element::tests::without_indent::enum_struct
    se::element::tests::without_indent::enum_tuple
    se::element::tests::without_indent::enum_unit
    se::element::tests::without_indent::enum_unit_escaped
  serde-se (10):
    without_root::enum_::externally_tagged::normal_field2::empty_struct
    without_root::enum_::externally_tagged::normal_field2::newtype
    without_root::enum_::externally_tagged::normal_field2::struct_
    without_root::enum_::externally_tagged::normal_field2::tuple
    without_root::enum_::externally_tagged::normal_field::empty_struct
    without_root::enum_::externally_tagged::normal_field::newtype
    without_root::enum_::externally_tagged::normal_field::struct_
    without_root::enum_::externally_tagged::normal_field::tuple
    without_root::enum_::externally_tagged::text_variant::normal_field::newtype
    without_root::enum_::externally_tagged::text_variant::normal_field::tuple
failures (1):
    without_root::enum_::externally_tagged::text_variant::text_field::unit

Fixed (5):
    without_root::enum_::externally_tagged::normal_field2::unit
    without_root::enum_::externally_tagged::normal_field::unit
    without_root::enum_::externally_tagged::text_variant::normal_field::unit
Fixed (1):
    without_root::enum_::externally_tagged::text_variant::text_field::uni
@dralley
Copy link
Collaborator

dralley commented Oct 19, 2023

I don't have time to review this this week. Merge away

@Mingun
Copy link
Collaborator Author

Mingun commented Oct 19, 2023

@dralley , heh, I not quite experienced in English slang. "Merge away" -- is this "ok, you can merge this, I anyway does not known serde's much" or "please don't merge, I want to do a review when I'll have time" 😅?

@dralley
Copy link
Collaborator

dralley commented Oct 19, 2023

It means you can merge it freely without needing my say so

You can merge it, yes.

@Mingun Mingun merged commit 569ac22 into tafia:master Oct 20, 2023
6 checks passed
@Mingun Mingun deleted the fix-serde181-compatibility branch October 20, 2023 16:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

serde >=1.0.181 has breaking changes that fails enum_::adjacently_tagged tests
2 participants