lumeohq / xsd-parser-rs

A xsd/wsdl => rust code generator written in rust
Apache License 2.0
100 stars 39 forks source link

Add choice element support for complex type #13

Closed LeonidKrutovsky closed 4 years ago

LeonidKrutovsky commented 4 years ago
<xs:complexType name="ColorOptions">
    <xs:annotation>
        <xs:documentation>
            Describe the colors supported. Either list each color or define the range of color values.
        </xs:documentation>
    </xs:annotation>
    <xs:choice>
        <xs:element name="ColorList" type="tt:Color" maxOccurs="unbounded">
            <xs:annotation>
                <xs:documentation>List the supported color.</xs:documentation>
            </xs:annotation>
        </xs:element>
        <xs:element name="ColorspaceRange" type="tt:ColorspaceRange" maxOccurs="unbounded">
            <xs:annotation>
                <xs:documentation>Define the range of color supported.</xs:documentation>
            </xs:annotation>
        </xs:element>
    </xs:choice>
    <xs:anyAttribute processContents="lax"/>
</xs:complexType>

https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms256109(v=vs.100)

LeonidKrutovsky commented 4 years ago
pub enum ColorOptionsChoice {
  ColorList(Vec<Color>),  // List the supported color.
  ColorspaceRange(Vec<ColorspaceRange>), // Define the range of color supported.
}

// Describe the colors supported. Either list each color or define the range of color values.
pub struct ColorOptions {
  choice: ColorOptionsChoice,
  any_attribute: AnyAttribute,
} 
victor-soloviev commented 4 years ago

We got a problem here: yaserde currently does not support de/serialization of enums with associated values

this one is supported:

#[derive(PartialEq, Debug, YaSerialize)]
enum IpAddrKind {
    V4,
    V6,
}

this one is not:

#[derive(PartialEq, Debug, YaSerialize)]
enum IpAddrKind {
    V4 (String),
    V6 (String),
}

Perhaps we could patch yaserde as Dmitry has done before for other issues.

Related issue: https://github.com/media-io/yaserde/issues/8

DmitrySamoylov commented 4 years ago

Yaserde is patched to support this: https://github.com/media-io/yaserde/pull/30 It works since yaserde 0.3.10 (already on crates.io)

Example use of type with 'choice' elements in onvif-rs: https://github.com/lumeohq/onvif-rs/commit/6e60f6187e76e959336d1ef28fae768f8124e216

There is still an open question on how to deal with attributes in enums:

Variant 1 (now in onvif-rs):

pub enum ColorOptions {
    ColorList(Vec<Color>),
    ColorspaceRange(Vec<ColorspaceRange>),
}

Corresponding XML could be like:

<tt:ColorOptions xmlns:tt="http://www.onvif.org/ver10/schema">
    <tt:ColorspaceRange>
        <X>0.1</X>
        <Y>0.2</Y>
        <Z>0.3</Z>
        <Colorspace>http://my.color.space</Colorspace>
    </tt:ColorspaceRange>
    <tt:ColorspaceRange>
        <X>0.5</X>
        <Y>0.6</Y>
        <Z>0.7</Z>
        <Colorspace>http://my.color.space</Colorspace>
    </tt:ColorspaceRange>
</tt:ColorOptions>

This variant does not support attributes because attributes are supposed to be a struct field in rust but there are no fields in enums.

Variant 2 (initially proposed by @LeonidKrutovsky ):

pub enum ColorOptionsChoice {
  ColorList(Vec<Color>), 
  ColorspaceRange(Vec<ColorspaceRange>), 
}

pub struct ColorOptions {
  choice: ColorOptionsChoice,
  any_attribute: AnyAttribute,
} 

In this case yaserde will expect something like

<tt:ColorOptions xmlns:tt="http://www.onvif.org/ver10/schema">
  <choice>
    <tt:ColorspaceRange>
    ...

and will fail for sure.

Variant 3

Don't use enums at all. Use Option or Vec for each choice variant:

pub struct ColorOptions {
    color_list: Vec<Color>,
    colorspace_range: Vec<ColorspaceRange>,
    any_attribute: AnyAttribute,
}

It'll work but it is semantically not precise.

Variant 4

Keep variant 2 and implement 'deserialize' for each such case manually. Grep shows only 5 matches for '' across all xsd/wsdl's. So it may work if we find out how to use custom deserializers (https://github.com/media-io/yaserde/issues/25)