Stop being pedantic by default

Up to now, the xmpp-rs projects have been very strict about incoming
data. This has served us, as developers of the libraries, well,
uncovering bugs in our and remote implementations which we could then
get fixed.

However, this behaviour is unexpected to users of the library. In the
XMPP world, unexpected child elements and attributes are generally
expected to be ignored. While this could be opted-into previously, the
feature flag for that sounded more dangerous than it was
("disable-validation"). In addition, the tribal knowledge needed to know
about that feature flag may not have reached some people who tried the
library and gave up because of that.

With this change, we make the non-pedantic behaviour the default. For
development and debugging purposes, users can always opt into the
pedantic behaviour as needed, using the newly-introduced `pedantic`
feature flags on all affected crates.
This commit is contained in:
Jonas Schäfer 2026-03-27 12:07:53 +01:00
commit e2dcd8ac66
41 changed files with 99 additions and 107 deletions

View file

@ -32,8 +32,8 @@ serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
[features]
# Build xmpp-parsers to make components instead of clients.
component = []
# Disable validation of unknown attributes.
disable-validation = [ "xso/non-pedantic" ]
# Raise errors on unexpected children and attributes.
pedantic = [ "xso/pedantic" ]
# Enable serde support in jid crate
serde = [ "jid/serde" ]
# Enable some additional logging in helpers

View file

@ -18,6 +18,10 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
- bind::BindFeature::required is now a bool, thanks to xsos flag.
- jingle_rtp::Description::rtcp_mux is now a bool flag too.
- stream_limits::Limits now extract directly to NonZeroU32.
- Removed the `disable-validation` feature and made the behaviour the
new default. That way, unknown child elements and attributes will
not be rejected by xmpp-parsers by default anymore. The `pedantic`
feature can be used to opt into the previous default behaviour.
* Improvements:
- Make Prioritys inner i8 pub, which had been broken since the
conversion to xso. (!632)

View file

@ -19,7 +19,7 @@ impl MessagePayload for Attention {}
mod tests {
use super::*;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[test]
@ -33,7 +33,7 @@ mod tests {
Attention::try_from(elem).unwrap();
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_child() {
let elem: Element = "<attention xmlns='urn:xmpp:attention:0'><coucou/></attention>"
@ -47,7 +47,7 @@ mod tests {
assert_eq!(message, "Unknown child in Attention element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<attention xmlns='urn:xmpp:attention:0' coucou=''/>"

View file

@ -69,7 +69,7 @@ mod tests {
use super::*;
use crate::hashes::Algo;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[cfg(target_pointer_width = "32")]
@ -121,7 +121,7 @@ mod tests {
assert_eq!(data.data, b"\0\0\0");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid() {
let elem: Element = "<data xmlns='urn:xmpp:avatar:data' id='coucou'/>"

View file

@ -72,7 +72,7 @@ impl From<BindResponse> for Jid {
mod tests {
use super::*;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[cfg(target_pointer_width = "32")]
@ -118,7 +118,7 @@ mod tests {
);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_resource() {
let elem: Element = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource attr='coucou'>resource</resource></bind>"

View file

@ -62,7 +62,7 @@ pub struct Blocked;
#[cfg(test)]
mod tests {
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
use super::*;
@ -126,7 +126,7 @@ mod tests {
assert_eq!(unblock.items, two_items);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid() {
let elem: Element = "<blocklist xmlns='urn:xmpp:blocking' coucou=''/>"
@ -169,7 +169,7 @@ mod tests {
assert_eq!(message, "Unknown attribute in Unblock element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_non_empty_blocklist_request() {
let elem: Element = "<blocklist xmlns='urn:xmpp:blocking'><item jid='coucou@coucou'/><item jid='domain'/></blocklist>".parse().unwrap();

View file

@ -187,7 +187,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn unknown_child() {
let elem: Element = "<data xmlns='urn:xmpp:bob' cid='sha1+8f35fef110ffc5df08d579a50083ff9308fb6242@bob.xmpp.org'><coucou/></data>"
.parse()

View file

@ -197,7 +197,7 @@ mod tests {
use super::*;
use crate::caps;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[cfg(target_pointer_width = "32")]
@ -226,7 +226,7 @@ mod tests {
);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_child() {
let elem: Element = "<c xmlns='http://jabber.org/protocol/caps' node='coucou' hash='sha-256' ver='K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4='><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash></c>".parse().unwrap();

View file

@ -70,7 +70,7 @@ mod tests {
assert_eq!(message, "This is not a ChatState element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_child() {
let elem: Element = "<gone xmlns='http://jabber.org/protocol/chatstates'><coucou/></gone>"
@ -84,7 +84,7 @@ mod tests {
assert_eq!(message, "Unknown child in ChatState::Gone element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<inactive xmlns='http://jabber.org/protocol/chatstates' coucou=''/>"

View file

@ -485,7 +485,7 @@ mod tests {
}
#[test]
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
fn test_wrong_child() {
let elem: Element = "<x xmlns='jabber:x:data' type='cancel'><coucou/></x>"
.parse()

View file

@ -449,7 +449,7 @@ mod tests {
#[test]
#[cfg_attr(
feature = "disable-validation",
not(feature = "pedantic"),
should_panic = "Validate::try_from(element).is_err()"
)]
fn test_fails_with_invalid_children() {

View file

@ -81,7 +81,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<delay xmlns='urn:xmpp:delay' stamp='2002-09-10T23:08:25+00:00'><coucou/></delay>"

View file

@ -241,7 +241,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid() {
let elem: Element =
"<query xmlns='http://jabber.org/protocol/disco#info'><coucou/></query>"

View file

@ -233,7 +233,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<c xmlns='urn:xmpp:caps'><hash xmlns='urn:xmpp:hashes:2' algo='sha-256'>K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=</hash><hash xmlns='urn:xmpp:hashes:1' algo='sha3-256'>+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=</hash></c>".parse().unwrap();
let error = ECaps2::try_from(elem).unwrap_err();

View file

@ -72,7 +72,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<encryption xmlns='urn:xmpp:eme:0' namespace='urn:xmpp:otr:0'><coucou/></encryption>"

View file

@ -58,7 +58,7 @@ mod tests {
#[test]
#[cfg(not(feature = "component"))] // feature = "component" changes <message/> namespace
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><message xmlns='jabber:client'/><coucou/></forwarded>"
.parse()

View file

@ -305,7 +305,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<hash xmlns='urn:xmpp:hashes:2' algo='sha-1'><coucou/></hash>"
.parse()

View file

@ -42,7 +42,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'><coucou/></idle>"

View file

@ -770,7 +770,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child_in_reason() {
let elem: Element = "<jingle xmlns='urn:xmpp:jingle:1' action='session-initiate' sid='coucou'><reason><decline/><a/></reason></jingle>".parse().unwrap();
let error = Jingle::try_from(elem).unwrap_err();

View file

@ -316,7 +316,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_received_unknown_child() {
let elem: Element = "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator'><coucou/></received>".parse().unwrap();
let error = Received::try_from(elem).unwrap_err();
@ -358,7 +358,7 @@ mod tests {
);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_received() {
let elem: Element = "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''/>".parse().unwrap();
@ -401,7 +401,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_checksum_unknown_child() {
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator'><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file><coucou/></checksum>".parse().unwrap();
let error = Checksum::try_from(elem).unwrap_err();
@ -440,7 +440,7 @@ mod tests {
);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_checksum() {
let elem: Element = "<checksum xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='initiator' coucou=''><file><hash xmlns='urn:xmpp:hashes:2' algo='sha-1'>w0mcJylzCn+AfvuGdqkty2+KP48=</hash></file></checksum>".parse().unwrap();
@ -481,7 +481,7 @@ mod tests {
assert_eq!(range2.hashes, hashes);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_range() {
let elem: Element = "<range xmlns='urn:xmpp:jingle:apps:file-transfer:5' coucou=''/>"

View file

@ -300,7 +300,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<query xmlns='urn:xmpp:mam:2'><coucou/></query>"
.parse()

View file

@ -154,7 +154,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_unknown_child() {
let elem: Element = "<media xmlns='urn:xmpp:media-element'><coucou/></media>"
.parse()

View file

@ -47,7 +47,7 @@ mod tests {
Replace::try_from(elem).unwrap();
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<replace xmlns='urn:xmpp:message-correct:0' id='coucou' coucou=''/>"
@ -62,7 +62,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<replace xmlns='urn:xmpp:message-correct:0' id='coucou'><coucou/></replace>"

View file

@ -127,7 +127,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_muc_invalid_child() {
let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'><coucou/></x>"
.parse()
@ -153,7 +153,7 @@ mod tests {
assert_eq!(elem, elem2);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_muc_invalid_attribute() {
let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>"

View file

@ -403,7 +403,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<x xmlns='http://jabber.org/protocol/muc#user'>
<coucou/>
@ -433,7 +433,7 @@ mod tests {
assert_eq!(elem, elem2);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<x xmlns='http://jabber.org/protocol/muc#user' coucou=''/>"
@ -468,7 +468,7 @@ mod tests {
assert_eq!(message, "Required attribute 'code' missing.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_status_invalid_child() {
let elem: Element = "<status xmlns='http://jabber.org/protocol/muc#user' code='110'>
@ -579,7 +579,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_continue_invalid() {
let elem: Element =
"<continue xmlns='http://jabber.org/protocol/muc#user'><foobar/></continue>"
@ -606,7 +606,7 @@ mod tests {
assert_eq!(elem2, elem3);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_reason_invalid_attribute() {
let elem: Element = "<reason xmlns='http://jabber.org/protocol/muc#user' foo='bar'/>"
@ -620,7 +620,7 @@ mod tests {
assert_eq!(message, "Unknown attribute in Reason element.".to_owned());
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_reason_invalid() {
let elem: Element = "<reason xmlns='http://jabber.org/protocol/muc#user'>
@ -636,7 +636,7 @@ mod tests {
assert_eq!(message, "Unknown child in Reason element.".to_owned());
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_item_invalid_attr() {
let elem: Element = "<item xmlns='http://jabber.org/protocol/muc#user'

View file

@ -15,7 +15,7 @@ generate_elem_id!(
mod tests {
use super::*;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[cfg(target_pointer_width = "32")]
@ -48,7 +48,7 @@ mod tests {
assert_eq!(elem1, elem2);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid() {
let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick'><coucou/></nick>"
@ -62,7 +62,7 @@ mod tests {
assert_eq!(message, "Unknown child in Nick element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<nick xmlns='http://jabber.org/protocol/nick' coucou=''/>"

View file

@ -53,7 +53,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<occupant-id xmlns='urn:xmpp:occupant-id:0' id='foo'><coucou/></occupant-id>"

View file

@ -22,7 +22,7 @@ impl IqGetPayload for Ping {}
mod tests {
use super::*;
use minidom::Element;
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
use xso::error::{Error, FromElementError};
#[test]
@ -43,7 +43,7 @@ mod tests {
assert_eq!(elem1, elem2);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid() {
let elem: Element = "<ping xmlns='urn:xmpp:ping'><coucou/></ping>"
@ -57,7 +57,7 @@ mod tests {
assert_eq!(message, "Unknown child in Ping element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<ping xmlns='urn:xmpp:ping' coucou=''/>".parse().unwrap();

View file

@ -533,7 +533,7 @@ mod tests {
assert!(payload.is("test", "invalid"));
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_status_child() {
#[cfg(not(feature = "component"))]
@ -556,7 +556,7 @@ mod tests {
);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
#[cfg(not(feature = "component"))]

View file

@ -278,7 +278,7 @@ mod tests {
assert_eq!(message, "This is not a Payload element.");
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid_attribute() {
let elem: Element = "<event xmlns='http://jabber.org/protocol/pubsub#event' coucou=''/>"

View file

@ -264,7 +264,7 @@ mod tests {
assert_eq!(roster.items[0].subscription, Subscription::Remove);
}
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
#[test]
fn test_invalid() {
let elem: Element = "<query xmlns='jabber:iq:roster'><coucou/></query>"
@ -317,7 +317,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_item_unknown_child() {
let elem: Element =
"<query xmlns='jabber:iq:roster'><item jid='coucou'><coucou/></item></query>"

View file

@ -130,7 +130,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element = "<set xmlns='http://jabber.org/protocol/rsm'><coucou/></set>"
.parse()

View file

@ -263,7 +263,7 @@ mod tests {
/// Some servers apparently use a non-namespaced 'lang' attribute, which is invalid as not part
/// of the schema. This tests whether we can parse it when disabling validation.
#[cfg(feature = "disable-validation")]
#[cfg(not(feature = "pedantic"))]
#[test]
fn invalid_failure_with_non_prefixed_text_lang() {
let elem: Element = "<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>

View file

@ -76,7 +76,7 @@ mod tests {
}
#[test]
#[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")]
#[cfg_attr(not(feature = "pedantic"), should_panic = "Result::unwrap_err")]
fn test_invalid_child() {
let elem: Element =
"<stanza-id xmlns='urn:xmpp:sid:0' by='a@b' id='x'><coucou/></stanza-id>"

View file

@ -121,10 +121,7 @@ fn empty_namespace_mismatch() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn empty_unexpected_attribute() {
#[allow(unused_imports)]
use core::{
@ -153,10 +150,7 @@ fn empty_ignores_xml_lang() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn empty_unexpected_child() {
#[allow(unused_imports)]
use core::{
@ -944,10 +938,7 @@ fn text_extract_negative_absent_child() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn text_extract_negative_unexpected_attribute_in_child() {
#[allow(unused_imports)]
use core::{
@ -961,10 +952,7 @@ fn text_extract_negative_unexpected_attribute_in_child() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn text_extract_negative_unexpected_child_in_child() {
#[allow(unused_imports)]
use core::{
@ -1647,7 +1635,7 @@ fn element_catch_one_negative_none() {
}
#[test]
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
fn element_catch_one_negative_more_than_one_child() {
#[allow(unused_imports)]
use core::{
@ -1690,7 +1678,7 @@ fn element_catch_maybe_one_roundtrip_some() {
}
#[test]
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
fn element_catch_maybe_one_negative_more_than_one_child() {
#[allow(unused_imports)]
use core::{
@ -2073,10 +2061,7 @@ fn ignore_unknown_attributes_positive() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn ignore_unknown_attributes_negative_unexpected_child() {
#[allow(unused_imports)]
use core::{
@ -2119,10 +2104,7 @@ fn ignore_unknown_children_positive() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn ignore_unknown_children_negative_unexpected_attribute() {
#[allow(unused_imports)]
use core::{
@ -2265,10 +2247,7 @@ fn discard_attribute_absent_roundtrip() {
}
#[test]
#[cfg_attr(
feature = "disable-validation",
should_panic = "unexpected result: Ok("
)]
#[cfg_attr(not(feature = "pedantic"), should_panic = "unexpected result: Ok(")]
fn discard_attribute_fails_on_other_unexpected_attributes() {
#[allow(unused_imports)]
use core::{

View file

@ -318,7 +318,7 @@ macro_rules! check_ns_only {
macro_rules! check_no_children {
($elem:ident, $name:tt) => {
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
for _ in $elem.children() {
return Err(xso::error::Error::Other(
concat!("Unknown child in ", $name, " element.").into(),
@ -330,7 +330,7 @@ macro_rules! check_no_children {
macro_rules! check_no_attributes {
($elem:ident, $name:tt) => {
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
for _ in $elem.attrs() {
return Err(xso::error::Error::Other(
concat!("Unknown attribute in ", $name, " element.").into(),
@ -342,7 +342,7 @@ macro_rules! check_no_attributes {
macro_rules! check_no_unknown_attributes {
($elem:ident, $name:tt, [$($attr:tt),*]) => (
#[cfg(not(feature = "disable-validation"))]
#[cfg(feature = "pedantic")]
for ((ns, attr), _) in $elem.attrs() {
$(
if *ns == ::xso::exports::rxml::Namespace::NONE && attr == $attr {

View file

@ -90,7 +90,7 @@ serde = [ "xmpp-parsers/serde" ]
dns = [ "hickory-resolver", "idna" ]
component = ["xmpp-parsers/component", "insecure-tcp"]
disable-validation = ["xmpp-parsers/disable-validation"]
pedantic = ["xmpp-parsers/pedantic"]
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(xmpprs_doc_build)'] }

View file

@ -1,5 +1,10 @@
Version NEXT:
0000-00-00 RELEASER <releaser@domain>
* Breaking:
- Removed the `disable-validation` feature and made the behaviour the
new default. The newly-introduced `pedantic` feature can be used to
opt into the previous default behaviour of rejecting all unknown
child elements and attributes.
* Added:
- Expose `client_auth` method to allow manual stream setups for advanced
use cases.

View file

@ -31,7 +31,7 @@ default = [ "std" ]
macros = [ "dep:xso_proc", "rxml/macros" ]
minidom = [ "xso_proc/minidom"]
panicking-into-impl = ["xso_proc/panicking-into-impl"]
non-pedantic = []
pedantic = []
std = []
[package.metadata.docs.rs]

View file

@ -1,4 +1,8 @@
Version NEXT:
* Breaking
- Removed the `non-pedantic` feature and made the behaviour the default.
- Added the `pedantic` feature, opting into the previous default
behaviour of rejecting unknown attributes and children.
* Changes
- Fix some Clippy warnings
- Fix build with minidom and without std (!661)

View file

@ -349,17 +349,17 @@ pub trait AsOptionalXmlText {
pub enum UnknownAttributePolicy {
/// All unknown attributes are discarded.
///
/// This is the default policy if the crate is built with the
/// `non-pedantic` feature.
#[cfg_attr(feature = "non-pedantic", default)]
/// This is the default policy if the crate is built without the
/// `pedantic` feature.
#[cfg_attr(not(feature = "pedantic"), default)]
Discard,
/// The first unknown attribute which is encountered generates a fatal
/// parsing error.
///
/// This is the default policy if the crate is built **without** the
/// `non-pedantic` feature.
#[cfg_attr(not(feature = "non-pedantic"), default)]
/// This is the default policy if the crate is built with the
/// `pedantic` feature.
#[cfg_attr(feature = "pedantic", default)]
Fail,
}
@ -386,17 +386,17 @@ impl UnknownAttributePolicy {
pub enum UnknownChildPolicy {
/// All unknown children are discarded.
///
/// This is the default policy if the crate is built with the
/// `non-pedantic` feature.
#[cfg_attr(feature = "non-pedantic", default)]
/// This is the default policy if the crate is built without the
/// `pedantic` feature.
#[cfg_attr(not(feature = "pedantic"), default)]
Discard,
/// The first unknown child which is encountered generates a fatal
/// parsing error.
///
/// This is the default policy if the crate is built **without** the
/// `non-pedantic` feature.
#[cfg_attr(not(feature = "non-pedantic"), default)]
/// This is the default policy if the crate is built with the
/// `pedantic` feature.
#[cfg_attr(feature = "pedantic", default)]
Fail,
}