Skip to content

Commit

Permalink
Merge branch 'borgoat-fix/vec-option-complex-types'
Browse files Browse the repository at this point in the history
  • Loading branch information
MarcAntoine-Arnaud committed Feb 14, 2024
2 parents b064bb7 + fec1793 commit a6a5b58
Show file tree
Hide file tree
Showing 3 changed files with 318 additions and 18 deletions.
60 changes: 60 additions & 0 deletions xml_schema/tests/dmarc_rua.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use xml_schema_derive::XmlSchema;
use yaserde::de::from_str;

#[test]
fn dmarc_rua_string() {
#[derive(Debug, XmlSchema)]
#[xml_schema(source = "xml_schema/tests/dmarc_rua.xsd", target_prefix = "dmarc")]
struct DmarcRuaSchema;

let xml_1 = r#"<?xml version="1.0" encoding="UTF-8" ?>
<feedback>
<report_metadata>
<org_name>google.com</org_name>
<email>[email protected]</email>
<extra_contact_info>https://support.google.com/a/answer/2466580</extra_contact_info>
<report_id>5717107811868587391</report_id>
<date_range>
<begin>1706832000</begin>
<end>1706918399</end>
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<sp>none</sp>
<pct>100</pct>
<np>none</np>
</policy_published>
<record>
<row>
<source_ip>185.70.43.17</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>pass</dkim>
<spf>pass</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<domain>example.com</domain>
<result>pass</result>
<selector>protonmail2</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
</spf>
</auth_results>
</record>
</feedback>
"#;

let _: Feedback = from_str(xml_1).unwrap();
}
244 changes: 244 additions & 0 deletions xml_schema/tests/dmarc_rua.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://dmarc.org/dmarc-xml/0.1"
targetNamespace="http://dmarc.org/dmarc-xml/0.1">
<!--
The time range in UTC covered by messages in this report, specified in seconds since epoch.
-->
<xs:complexType name="DateRangeType">
<xs:all>
<xs:element name="begin" type="xs:integer"/>
<xs:element name="end" type="xs:integer"/>
</xs:all>
</xs:complexType>
<!-- Report generator metadata -->
<xs:complexType name="ReportMetadataType">
<xs:sequence>
<xs:element name="org_name" type="xs:string"/>
<xs:element name="email" type="xs:string"/>
<xs:element name="extra_contact_info" type="xs:string" minOccurs="0"/>
<xs:element name="report_id" type="xs:string"/>
<xs:element name="date_range" type="DateRangeType"/>
<xs:element name="error" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
Alignment mode (relaxed or strict) for DKIM and SPF.
-->
<xs:simpleType name="AlignmentType">
<xs:restriction base="xs:string">
<xs:enumeration value="r"/>
<xs:enumeration value="s"/>
</xs:restriction>
</xs:simpleType>
<!--
The policy actions specified by p and sp in the DMARC record.
-->
<xs:simpleType name="DispositionType">
<xs:restriction base="xs:string">
<xs:enumeration value="none"/>
<xs:enumeration value="quarantine"/>
<xs:enumeration value="reject"/>
</xs:restriction>
</xs:simpleType>
<!--
The DMARC policy that applied to the messages in this report.
-->
<xs:complexType name="PolicyPublishedType">
<xs:all>
<!-- The domain at which the DMARC record was found. -->
<xs:element name="domain" type="xs:string"/>
<!-- The DKIM alignment mode. -->
<xs:element name="adkim" type="AlignmentType"/>
<!-- The SPF alignment mode. -->
<xs:element name="aspf" type="AlignmentType"/>
<!-- The policy to apply to messages from the domain. -->
<xs:element name="p" type="DispositionType"/>
<!-- The policy to apply to messages from subdomains. -->
<xs:element name="sp" type="DispositionType"/>
<!-- The percent of messages to which policy applies. -->
<xs:element name="pct" type="xs:integer"/>
</xs:all>
</xs:complexType>
<!-- The DMARC-aligned authentication result. -->
<xs:simpleType name="DMARCResultType">
<xs:restriction base="xs:string">
<xs:enumeration value="pass"/>
<xs:enumeration value="fail"/>
</xs:restriction>
</xs:simpleType>
<!--
Reasons that may affect DMARC disposition or execution thereof.
-->
<!--
==============================================================
Descriptions of the PolicyOverrideTypes:
forwarded: Message was relayed via a known forwarder, or local
heuristics identified the message as likely having been forwarded.
There is no expectation that authentication would pass.
local_policy: The Mail Receiver's local policy exempted the message
from being subjected to the Domain Owner's requested policy
action.
mailing_list: Local heuristics determined that the message arrived
via a mailing list, and thus authentication of the original
message was not expected to succeed.
other: Some policy exception not covered by the other entries in
this list occurred. Additional detail can be found in the
PolicyOverrideReason's "comment" field.
sampled_out: Message was exempted from application of policy by the
"pct" setting in the DMARC policy record.
trusted_forwarder: Message authentication failure was anticipated by
other evidence linking the message to a locally-maintained list of
known and trusted forwarders.
==============================================================
-->
<xs:simpleType name="PolicyOverrideType">
<xs:restriction base="xs:string">
<xs:enumeration value="forwarded"/>
<xs:enumeration value="sampled_out"/>
<xs:enumeration value="trusted_forwarder"/>
<xs:enumeration value="mailing_list"/>
<xs:enumeration value="local_policy"/>
<xs:enumeration value="other"/>
</xs:restriction>
</xs:simpleType>
<!--
How do we allow report generators to include new classes of override reasons if they want to be more specific than "other"?
-->
<xs:complexType name="PolicyOverrideReason">
<xs:all>
<xs:element name="type" type="PolicyOverrideType"/>
<xs:element name="comment" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
<!--
Taking into account everything else in the record, the results of applying DMARC.
-->
<xs:complexType name="PolicyEvaluatedType">
<xs:sequence>
<xs:element name="disposition" type="DispositionType"/>
<xs:element name="dkim" type="DMARCResultType"/>
<xs:element name="spf" type="DMARCResultType"/>
<xs:element name="reason" type="PolicyOverrideReason" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
Credit to Roger L. Costello for IPv4 regex http://mailman.ic.ac.uk/pipermail/xml-dev/1999-December/018018.html
-->
<!--
Credit to java2s.com for IPv6 regex http://www.java2s.com/Code/XML/XML-Schema/IPv6addressesareeasiertodescribeusingasimpleregex.htm
-->
<xs:simpleType name="IPAddress">
<xs:restriction base="xs:string">
<xs:pattern
value="((1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]).){3}(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])|([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="RowType">
<xs:all>
<!-- The connecting IP. -->
<xs:element name="source_ip" type="IPAddress"/>
<!-- The number of matching messages -->
<xs:element name="count" type="xs:integer"/>
<!--
The DMARC disposition applying to matching messages.
-->
<xs:element name="policy_evaluated" type="PolicyEvaluatedType" minOccurs="0"/>
</xs:all>
</xs:complexType>
<xs:complexType name="IdentifierType">
<xs:all>
<!-- The envelope recipient domain. -->
<xs:element name="envelope_to" type="xs:string" minOccurs="0"/>
<!-- The payload From domain. -->
<xs:element name="header_from" type="xs:string" minOccurs="1"/>
</xs:all>
</xs:complexType>
<!--
DKIM verification result, according to RFC 5451 Section 2.4.1.
-->
<xs:simpleType name="DKIMResultType">
<xs:restriction base="xs:string">
<xs:enumeration value="none"/>
<xs:enumeration value="pass"/>
<xs:enumeration value="fail"/>
<xs:enumeration value="policy"/>
<xs:enumeration value="neutral"/>
<xs:enumeration value="temperror"/>
<xs:enumeration value="permerror"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="DKIMAuthResultType">
<xs:all>
<!-- The d= parameter in the signature -->
<xs:element name="domain" type="xs:string" minOccurs="1"/>
<!-- The "s=" parameter in the signature. -->
<xs:element name="selector" type="xs:string" minOccurs="0"/>
<!-- The DKIM verification result -->
<xs:element name="result" type="DKIMResultType" minOccurs="1"/>
<!--
Any extra information (e.g., from Authentication-Results
-->
<xs:element name="human_result" type="xs:string" minOccurs="0"/>
</xs:all>
</xs:complexType>
<!-- SPF result -->
<xs:simpleType name="SPFResultType">
<xs:restriction base="xs:string">
<xs:enumeration value="none"/>
<xs:enumeration value="neutral"/>
<xs:enumeration value="pass"/>
<xs:enumeration value="fail"/>
<xs:enumeration value="softfail"/>
<!-- "TempError" commonly implemented as "unknown" -->
<xs:enumeration value="temperror"/>
<!-- "PermError" commonly implemented as "error" -->
<xs:enumeration value="permerror"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="SPFAuthResultType">
<xs:all>
<!-- The envelope From domain. -->
<xs:element name="domain" type="xs:string" minOccurs="1"/>
<!-- The SPF verification result -->
<xs:element name="result" type="SPFResultType" minOccurs="1"/>
</xs:all>
</xs:complexType>
<!--
This element contains DKIM and SPF results, uninterpreted with respect to DMARC.
-->
<xs:complexType name="AuthResultType">
<xs:sequence>
<!--
There may be no DKIM signatures, or multiple DKIM signatures.
-->
<xs:element name="dkim" type="DKIMAuthResultType" minOccurs="0" maxOccurs="unbounded"/>
<!-- There will always be at least one SPF result. -->
<xs:element name="spf" type="SPFAuthResultType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
This element contains all the authentication results used to evaluate the DMARC disposition for the given set of messages.
-->
<xs:complexType name="RecordType">
<xs:sequence>
<xs:element name="row" type="RowType"/>
<xs:element name="identifiers" type="IdentifierType"/>
<xs:element name="auth_results" type="AuthResultType"/>
</xs:sequence>
</xs:complexType>
<!-- Parent -->
<xs:element name="feedback">
<xs:complexType>
<xs:sequence>
<xs:element name="report_metadata" type="ReportMetadataType"/>
<xs:element name="policy_published" type="PolicyPublishedType"/>
<xs:element name="record" type="RecordType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
32 changes: 14 additions & 18 deletions xml_schema_derive/src/xsd/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,23 +140,6 @@ impl Element {
);
};

let rust_type = if multiple {
quote!(Vec<#rust_type>)
} else {
rust_type
};

let rust_type = if !multiple && self.min_occurences == Some(0) {
quote!(Option<#rust_type>)
} else {
rust_type
};

let prefix_attribute = prefix
.as_ref()
.map(|prefix| quote!(, prefix=#prefix))
.unwrap_or_default();

let module = (!context.is_in_sub_module()
&& !self
.kind
Expand All @@ -169,9 +152,22 @@ impl Element {
.then_some(quote!(xml_schema_types::))
.unwrap_or_default();

let rust_type = if multiple {
quote!(Vec<#module#rust_type>)
} else if self.min_occurences == Some(0) {
quote!(Option<#module#rust_type>)
} else {
quote!(#module#rust_type)
};

let prefix_attribute = prefix
.as_ref()
.map(|prefix| quote!(, prefix=#prefix))
.unwrap_or_default();

quote! {
#[yaserde(rename=#yaserde_rename #prefix_attribute)]
pub #attribute_name: #module#rust_type,
pub #attribute_name: #rust_type,
}
}
}
Expand Down

0 comments on commit a6a5b58

Please sign in to comment.