xsd_parser::optimizer

Struct Optimizer

Source
pub struct Optimizer { /* private fields */ }
Expand description

The Optimizer is a structure that can be used to reduce the size and the complexity of a Types instance.

The optimizer contains different optimizations that could be applied to a Types instance. Optimizations are usually used to reduce the size or the complexity of the different types.

Implementations§

Source§

impl Optimizer

Source

pub fn new(types: Types) -> Self

Create a new Optimizer instance from the passed types.

Source

pub fn finish(self) -> Types

Finish the optimization and return the resulting Types.

Source

pub fn remove_empty_enum_variants(self) -> Self

This will remove any enum variant that has an empty string as name.

§Examples

Consider the following XML schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyEnum">
        <xs:restriction base="xs:string">
            <xs:enumeration value="" />
            <xs:enumeration value="Var1" />
            <xs:enumeration value="Var2" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyEnumType {
    Unknown1,
    Var1,
    Var2,
}

With this optimization the following code is generated:

pub enum MyEnumType {
    Var1,
    Var2,
}
Source

pub fn remove_empty_enums(self) -> Self

This will remove replace the enum with a type reference to the enums base type if the enum does not have any variant.

This optimization is usually used in combination with remove_empty_enum_variants.

§Examples

Consider the following XML schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyEnum">
        <xs:restriction base="xs:string">
            <xs:enumeration value="" />
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyEnumType {
    Unknown1,
}

With this optimization (and the remove_empty_enum_variants) the following code is generated:

pub type MyEnumType = StringType;
pub type StringType = String;
Source

pub fn remove_duplicate_union_variants(self) -> Self

This will remove variants of an union, if the type of the variant resolves to the same type as an other variant. In other words, the variant will be removed if the types are identical.

§Examples

Consider the following XML schema. xs:language and xs:string are both type definitions for String.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyUnion">
        <xs:union memberTypes="xs:language xs:string" />
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyUnionType {
    Language(LanguageType),
    String(StringType),
}
pub type LanguageType = String;
pub type StringType = String;

With this optimization the following code is generated:

pub enum MyUnionType {
    Language(LanguageType),
}
pub type LanguageType = String;
Source

pub fn remove_empty_unions(self) -> Self

This will replace an union with a simple type definition, if the union has only one variant.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyUnion">
        <xs:union memberTypes="xs:string" />
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyUnionType {
    String(StringType),
}
pub type StringType = String;

With this optimization the following code is generated:

pub type MyUnionType = StringType;
pub type StringType = String;
Source

pub fn use_unrestricted_base_type(self) -> Self

This will use the unrestricted base type instead more the restricted version when ever possible.

This is useful if you want to reduce the amount of different type, then the base type can store the same data than the restricted one. However this is only useful if you want to deserialize the type only. Using this feature for serializing types will cause problems because the type information is dropped during deserialization.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:complexType name="BaseType">
        <xs:sequence>
            <xs:element minOccurs="0" maxOccurs="unbounded" name="a" type="xs:string" />
            <xs:element minOccurs="0" maxOccurs="unbounded" name="b" type="xs:int" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="FirstRestrictedType">
        <xs:complexContent>
            <xs:restriction base="tns:BaseType">
                <xs:sequence>
                    <xs:element minOccurs="1" maxOccurs="1" name="a" type="xs:string" />
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="SecondRestrictedType">
        <xs:complexContent>
            <xs:restriction base="tns:BaseType">
                <xs:sequence>
                    <xs:element minOccurs="1" maxOccurs="unbounded" name="b" type="xs:int" />
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>

    <xs:complexType name="ThirdRestrictedType">
        <xs:complexContent>
            <xs:restriction base="tns:SecondRestrictedType">
                <xs:sequence>
                    <xs:element minOccurs="1" maxOccurs="1" name="b" type="xs:int" />
                </xs:sequence>
            </xs:restriction>
        </xs:complexContent>
    </xs:complexType>
</xs:schema>

Without this optimization this will result in the following code:

pub struct FirstRestrictedType {
    pub a: StringType,
}
pub type StringType = String;
pub struct SecondRestrictedType {
    pub b: Vec<IntType>,
}
pub type IntType = i32;
pub struct ThirdRestrictedType {
    pub b: IntType,
}

With this optimization the following code is generated:

pub type FirstRestrictedType = BaseType;
pub struct BaseType {
    pub a: Vec<StringType>,
    pub b: Vec<IntType>,
}
pub type StringType = String;
pub type IntType = i32;
pub type SecondRestrictedType = BaseType;
pub type ThirdRestrictedType = BaseType;
Source

pub fn convert_abstract_to_choice(self) -> Self

This will use a enum that contains all known variants of the abstract type instead of a dynamic box.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:element name="Abstract" abstract="true" />

    <xs:element name="First" substitutionGroup="tns:Abstract">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="a" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="Second" substitutionGroup="tns:Abstract">
        <xs:simpleType>
            <xs:restriction base="xs:token">
                <xs:enumeration value="Var1" />
                <xs:enumeration value="Var2" />
            </xs:restriction>
        </xs:simpleType>
    </xs:element>
</xs:schema>

Without this optimization this will result in the following code:

pub struct Abstract(Box<dyn core::any::Any>);
pub struct First {
    pub a: StringType,
}
pub enum Second {
    Var1,
    Var2,
}
pub type StringType = String;

With this optimization the following code is generated:

pub struct Abstract {
    pub content: AbstractContent,
}
pub enum AbstractContent {
    First(First),
    Second(Second),
}
pub struct First {
    pub a: StringType,
}
pub enum Second {
    Var1,
    Var2,
}
pub type StringType = String;
Source

pub fn flatten_element_content(self) -> Self

This will flatten the nested groups (xs::all, xs::choice or xs::sequence) to one type instead of rendering nested structures.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:complexType name="MyComplexType">
        <xs:sequence>
            <xs:element name="ElenentA" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
            <xs:element name="ElementB" type="xs:int" minOccurs="0" maxOccurs="unbounded" />
            <xs:choice>
                <xs:element name="ElementC" type="xs:boolean" />
                <xs:sequence minOccurs="0">
                    <xs:element name="ElenentD" type="xs:string" />
                    <xs:element name="ElementE" type="xs:int" />
                </xs:sequence>
                <xs:sequence>
                    <xs:element name="ElenentF" type="xs:string" />
                    <xs:element name="ElementG" type="xs:int" maxOccurs="unbounded" />
                </xs:sequence>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Without this optimization this will result in the following code:

pub struct MyComplexType {
    pub elenent_a: Vec<StringType>,
    pub element_b: Vec<IntType>,
    pub content_2: MyComplexContent2Type,
}
pub type StringType = String;
pub type IntType = i32;
pub struct MyComplexContent2Type {
    pub content: Option<MyComplexContent2TypeContent>,
}
pub enum MyComplexContent2TypeContent {
    ElementC(BooleanType),
    Content3(MyComplexContent3Type),
    Content4(MyComplexContent4Type),
}
pub type BooleanType = bool;
pub struct MyComplexContent3Type {
    pub elenent_d: StringType,
    pub element_e: IntType,
}
pub struct MyComplexContent4Type {
    pub elenent_f: StringType,
    pub element_g: Vec<IntType>,
}

With this optimization the following code is generated:

pub struct MyComplexType {
    pub content: Vec<MyComplexTypeContent>,
}
pub enum MyComplexTypeContent {
    ElenentA(StringType),
    ElementB(IntType),
    ElementC(BooleanType),
    ElenentD(StringType),
    ElementE(IntType),
    ElenentF(StringType),
    ElementG(IntType),
}
pub type StringType = String;
pub type IntType = i32;
pub type BooleanType = bool;
Source

pub fn flatten_unions(self) -> Self

This will flatten nested union types to one single union.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyBaseUnion">
        <xs:union memberTypes="xs:int">
            <xs:simpleType>
                <xs:list itemType="xs:unsignedInt" />
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>

    <xs:simpleType name="MyEnum">
        <xs:restriction base="xs:string">
            <xs:enumeration value="Var1" />
            <xs:enumeration value="Var2" />
        </xs:restriction>
    </xs:simpleType>

    <xs:simpleType name="MyUnion">
        <xs:union memberTypes="xs:string tns:MyEnum tns:MyBaseUnion" />
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyUnionType {
    String(StringType),
    MyEnum(MyEnumType),
    MyBaseUnion(MyBaseUnionType),
}
pub type StringType = String;
pub enum MyEnumType {
    Var1,
    Var2,
}
pub enum MyBaseUnionType {
    Int(IntType),
    Unnamed1(UnsignedIntList),
}
pub type IntType = i32;
#[derive(Default)]
pub struct UnsignedIntList(pub Vec<UnsignedIntType>);
pub type UnsignedIntType = u32;

With this optimization the following code is generated:

pub enum MyUnionType {
    String(String),
    MyEnum(MyEnumType),
    I32(i32),
    Unnamed1(UnsignedIntList),
}
pub enum MyEnumType {
    Var1,
    Var2,
}
#[derive(Default)]
pub struct UnsignedIntList(pub Vec<UnsignedIntType>);
pub type UnsignedIntType = u32;
Source

pub fn merge_enum_unions(self) -> Self

This will flatten nested union and enum types to one single enum type.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:simpleType name="MyBaseUnion">
        <xs:union memberTypes="xs:int">
            <xs:simpleType>
                <xs:list itemType="xs:unsignedInt" />
            </xs:simpleType>
        </xs:union>
    </xs:simpleType>

    <xs:simpleType name="MyEnum">
        <xs:restriction base="xs:string">
            <xs:enumeration value="Var1" />
            <xs:enumeration value="Var2" />
        </xs:restriction>
    </xs:simpleType>

    <xs:simpleType name="MyUnion">
        <xs:union memberTypes="xs:string tns:MyEnum tns:MyBaseUnion" />
    </xs:simpleType>
</xs:schema>

Without this optimization this will result in the following code:

pub enum MyUnionType {
    String(StringType),
    MyEnum(MyEnumType),
    MyBaseUnion(MyBaseUnionType),
}
pub type StringType = String;
pub enum MyEnumType {
    Var1,
    Var2,
}
pub enum MyBaseUnionType {
    Int(IntType),
    Unnamed1(UnsignedIntList),
}
pub type IntType = i32;
#[derive(Default)]
pub struct UnsignedIntList(pub Vec<UnsignedIntType>);
pub type UnsignedIntType = u32;

With this optimization the following code is generated:

pub enum MyUnionType {
    String(String),
    Var1,
    Var2,
    I32(i32),
    UnsignedIntList(UnsignedIntList),
}
#[derive(Default)]
pub struct UnsignedIntList(pub Vec<UnsignedIntType>);
pub type UnsignedIntType = u32;
Source

pub fn resolve_typedefs(self) -> Self

This will resolve all simple type definitions and use the target type directly.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:complexType name="MyComplexType">
        <xs:sequence>
            <xs:element name="ElenentA" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
            <xs:element name="ElementB" type="xs:int" minOccurs="0" maxOccurs="unbounded" />
            <xs:choice>
                <xs:element name="ElementC" type="xs:boolean" />
                <xs:sequence minOccurs="0">
                    <xs:element name="ElenentD" type="xs:string" />
                    <xs:element name="ElementE" type="xs:int" />
                </xs:sequence>
                <xs:sequence>
                    <xs:element name="ElenentF" type="xs:string" />
                    <xs:element name="ElementG" type="xs:int" maxOccurs="unbounded" />
                </xs:sequence>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Without this optimization this will result in the following code:

pub struct MyComplexType {
    pub elenent_a: Vec<StringType>,
    pub element_b: Vec<IntType>,
    pub content_2: MyComplexContent2Type,
}
pub type StringType = String;
pub type IntType = i32;
pub struct MyComplexContent2Type {
    pub content: Option<MyComplexContent2TypeContent>,
}
pub enum MyComplexContent2TypeContent {
    ElementC(BooleanType),
    Content3(MyComplexContent3Type),
    Content4(MyComplexContent4Type),
}
pub type BooleanType = bool;
pub struct MyComplexContent3Type {
    pub elenent_d: StringType,
    pub element_e: IntType,
}
pub struct MyComplexContent4Type {
    pub elenent_f: StringType,
    pub element_g: Vec<IntType>,
}

With this optimization the following code is generated:

pub struct MyComplexType {
    pub elenent_a: Vec<String>,
    pub element_b: Vec<i32>,
    pub content_2: MyComplexContent2Type,
}
pub struct MyComplexContent2Type {
    pub content: Option<MyComplexContent2TypeContent>,
}
pub enum MyComplexContent2TypeContent {
    ElementC(bool),
    Content3(MyComplexContent3Type),
    Content4(MyComplexContent4Type),
}
pub struct MyComplexContent3Type {
    pub elenent_d: String,
    pub element_e: i32,
}
pub struct MyComplexContent4Type {
    pub elenent_f: String,
    pub element_g: Vec<i32>,
}
Source

pub fn remove_duplicates(self) -> Self

If two types are completely equal this optimization will generate the first type complete and just a type definition for the second one.

§Examples

Consider the following XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://example.com"
    targetNamespace="http://example.com">

    <xs:complexType name="First">
        <xs:sequence>
            <xs:element name="a" type="xs:string" />
            <xs:element name="b" type="xs:string" minOccurs="0" />
            <xs:element name="c" type="xs:string" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="Second">
        <xs:sequence>
            <xs:element name="a" type="xs:string" />
            <xs:element name="b" type="xs:string" minOccurs="0" />
            <xs:element name="c" type="xs:string" maxOccurs="unbounded" />
        </xs:sequence>
    </xs:complexType>
</xs:schema>

Without this optimization this will result in the following code:

pub struct FirstType {
    pub a: StringType,
    pub b: Option<StringType>,
    pub c: Vec<StringType>,
}
pub type StringType = String;
pub struct SecondType {
    pub a: StringType,
    pub b: Option<StringType>,
    pub c: Vec<StringType>,
}

With this optimization the following code is generated:

pub type FirstType = SecondType;
pub struct SecondType {
    pub a: StringType,
    pub b: Option<StringType>,
    pub c: Vec<StringType>,
}
pub type StringType = String;

Trait Implementations§

Source§

impl Debug for Optimizer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> MaybeSendSync for T