parsers: port enums over to derive macros

This commit is contained in:
Jonas Schäfer 2024-07-10 16:38:00 +02:00
commit 6afd0ef52f
7 changed files with 563 additions and 428 deletions

View file

@ -1,5 +1,10 @@
Version NEXT:
XXXX-YY-ZZ RELEASER <admin@example.com>
* Breaking
- The `alternate_address` field of
`xmpp_parsers::stanza_error::StanzaError` has been moved into the
corresponding enum variants of the
`xmpp_parsers::stanza_error::DefinedCondition` where it may occur.
* New parsers/serialisers:
- Stream Features (RFC 6120) (!400)

View file

@ -4,28 +4,36 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{AsXml, FromXml};
use crate::message::MessagePayload;
use crate::ns;
generate_element_enum!(
/// Enum representing chatstate elements part of the
/// `http://jabber.org/protocol/chatstates` namespace.
ChatState, "chatstate", CHATSTATES, {
/// `<active xmlns='http://jabber.org/protocol/chatstates'/>`
Active => "active",
/// Enum representing chatstate elements part of the
/// `http://jabber.org/protocol/chatstates` namespace.
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::CHATSTATES, exhaustive)]
pub enum ChatState {
/// `<active xmlns='http://jabber.org/protocol/chatstates'/>`
#[xml(name = "active")]
Active,
/// `<composing xmlns='http://jabber.org/protocol/chatstates'/>`
Composing => "composing",
/// `<composing xmlns='http://jabber.org/protocol/chatstates'/>`
#[xml(name = "composing")]
Composing,
/// `<gone xmlns='http://jabber.org/protocol/chatstates'/>`
Gone => "gone",
/// `<gone xmlns='http://jabber.org/protocol/chatstates'/>`
#[xml(name = "gone")]
Gone,
/// `<inactive xmlns='http://jabber.org/protocol/chatstates'/>`
Inactive => "inactive",
/// `<inactive xmlns='http://jabber.org/protocol/chatstates'/>`
#[xml(name = "inactive")]
Inactive,
/// `<paused xmlns='http://jabber.org/protocol/chatstates'/>`
Paused => "paused",
}
);
/// `<paused xmlns='http://jabber.org/protocol/chatstates'/>`
#[xml(name = "paused")]
Paused,
}
impl MessagePayload for ChatState {}
@ -59,7 +67,7 @@ mod tests {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(message, "This is not a chatstate element.");
assert_eq!(message, "This is not a ChatState element.");
}
#[cfg(not(feature = "disable-validation"))]
@ -73,7 +81,7 @@ mod tests {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown child in chatstate element.");
assert_eq!(message, "Unknown child in ChatState::Gone element.");
}
#[cfg(not(feature = "disable-validation"))]
@ -87,7 +95,7 @@ mod tests {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(message, "Unknown attribute in chatstate element.");
assert_eq!(message, "Unknown attribute in ChatState::Inactive element.");
}
#[test]

View file

@ -232,15 +232,15 @@ mod tests {
#[cfg(target_pointer_width = "32")]
#[test]
fn test_size() {
assert_size!(IqType, 104);
assert_size!(Iq, 148);
assert_size!(IqType, 108);
assert_size!(Iq, 152);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_size() {
assert_size!(IqType, 208);
assert_size!(Iq, 296);
assert_size!(IqType, 216);
assert_size!(Iq, 304);
}
#[test]

View file

@ -4,262 +4,350 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
generate_element_enum!(
/// Enum representing all of the possible values of the XEP-0107 moods.
MoodEnum, "mood", MOOD, {
/// Impressed with fear or apprehension; in fear; apprehensive.
Afraid => "afraid",
use xso::{AsXml, FromXml};
/// Astonished; confounded with fear, surprise or wonder.
Amazed => "amazed",
use crate::ns;
/// Inclined to love; having a propensity to love, or to sexual enjoyment; loving, fond, affectionate, passionate, lustful, sexual, etc.
Amorous => "amorous",
/// Enum representing all of the possible values of the XEP-0107 moods.
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::MOOD, exhaustive)]
pub enum MoodEnum {
/// Impressed with fear or apprehension; in fear; apprehensive.
#[xml(name = "afraid")]
Afraid,
/// Displaying or feeling anger, i.e., a strong feeling of displeasure, hostility or antagonism towards someone or something, usually combined with an urge to harm.
Angry => "angry",
/// Astonished; confounded with fear, surprise or wonder.
#[xml(name = "amazed")]
Amazed,
/// To be disturbed or irritated, especially by continued or repeated acts.
Annoyed => "annoyed",
/// Inclined to love; having a propensity to love, or to sexual enjoyment; loving, fond, affectionate, passionate, lustful, sexual, etc.
#[xml(name = "amorous")]
Amorous,
/// Full of anxiety or disquietude; greatly concerned or solicitous, esp. respecting something future or unknown; being in painful suspense.
Anxious => "anxious",
/// Displaying or feeling anger, i.e., a strong feeling of displeasure, hostility or antagonism towards someone or something, usually combined with an urge to harm.
#[xml(name = "angry")]
Angry,
/// To be stimulated in one's feelings, especially to be sexually stimulated.
Aroused => "aroused",
/// To be disturbed or irritated, especially by continued or repeated acts.
#[xml(name = "annoyed")]
Annoyed,
/// Feeling shame or guilt.
Ashamed => "ashamed",
/// Full of anxiety or disquietude; greatly concerned or solicitous, esp. respecting something future or unknown; being in painful suspense.
#[xml(name = "anxious")]
Anxious,
/// Suffering from boredom; uninterested, without attention.
Bored => "bored",
/// To be stimulated in one's feelings, especially to be sexually stimulated.
#[xml(name = "aroused")]
Aroused,
/// Strong in the face of fear; courageous.
Brave => "brave",
/// Feeling shame or guilt.
#[xml(name = "ashamed")]
Ashamed,
/// Peaceful, quiet.
Calm => "calm",
/// Suffering from boredom; uninterested, without attention.
#[xml(name = "bored")]
Bored,
/// Taking care or caution; tentative.
Cautious => "cautious",
/// Strong in the face of fear; courageous.
#[xml(name = "brave")]
Brave,
/// Feeling the sensation of coldness, especially to the point of discomfort.
Cold => "cold",
/// Peaceful, quiet.
#[xml(name = "calm")]
Calm,
/// Feeling very sure of or positive about something, especially about one's own capabilities.
Confident => "confident",
/// Taking care or caution; tentative.
#[xml(name = "cautious")]
Cautious,
/// Chaotic, jumbled or muddled.
Confused => "confused",
/// Feeling the sensation of coldness, especially to the point of discomfort.
#[xml(name = "cold")]
Cold,
/// Feeling introspective or thoughtful.
Contemplative => "contemplative",
/// Feeling very sure of or positive about something, especially about one's own capabilities.
#[xml(name = "confident")]
Confident,
/// Pleased at the satisfaction of a want or desire; satisfied.
Contented => "contented",
/// Chaotic, jumbled or muddled.
#[xml(name = "confused")]
Confused,
/// Grouchy, irritable; easily upset.
Cranky => "cranky",
/// Feeling introspective or thoughtful.
#[xml(name = "contemplative")]
Contemplative,
/// Feeling out of control; feeling overly excited or enthusiastic.
Crazy => "crazy",
/// Pleased at the satisfaction of a want or desire; satisfied.
#[xml(name = "contented")]
Contented,
/// Feeling original, expressive, or imaginative.
Creative => "creative",
/// Grouchy, irritable; easily upset.
#[xml(name = "cranky")]
Cranky,
/// Inquisitive; tending to ask questions, investigate, or explore.
Curious => "curious",
/// Feeling out of control; feeling overly excited or enthusiastic.
#[xml(name = "crazy")]
Crazy,
/// Feeling sad and dispirited.
Dejected => "dejected",
/// Feeling original, expressive, or imaginative.
#[xml(name = "creative")]
Creative,
/// Severely despondent and unhappy.
Depressed => "depressed",
/// Inquisitive; tending to ask questions, investigate, or explore.
#[xml(name = "curious")]
Curious,
/// Defeated of expectation or hope; let down.
Disappointed => "disappointed",
/// Feeling sad and dispirited.
#[xml(name = "dejected")]
Dejected,
/// Filled with disgust; irritated and out of patience.
Disgusted => "disgusted",
/// Severely despondent and unhappy.
#[xml(name = "depressed")]
Depressed,
/// Feeling a sudden or complete loss of courage in the face of trouble or danger.
Dismayed => "dismayed",
/// Defeated of expectation or hope; let down.
#[xml(name = "disappointed")]
Disappointed,
/// Having one's attention diverted; preoccupied.
Distracted => "distracted",
/// Filled with disgust; irritated and out of patience.
#[xml(name = "disgusted")]
Disgusted,
/// Having a feeling of shameful discomfort.
Embarrassed => "embarrassed",
/// Feeling a sudden or complete loss of courage in the face of trouble or danger.
#[xml(name = "dismayed")]
Dismayed,
/// Feeling pain by the excellence or good fortune of another.
Envious => "envious",
/// Having one's attention diverted; preoccupied.
#[xml(name = "distracted")]
Distracted,
/// Having great enthusiasm.
Excited => "excited",
/// Having a feeling of shameful discomfort.
#[xml(name = "embarrassed")]
Embarrassed,
/// In the mood for flirting.
Flirtatious => "flirtatious",
/// Feeling pain by the excellence or good fortune of another.
#[xml(name = "envious")]
Envious,
/// Suffering from frustration; dissatisfied, agitated, or discontented because one is unable to perform an action or fulfill a desire.
Frustrated => "frustrated",
/// Having great enthusiasm.
#[xml(name = "excited")]
Excited,
/// Feeling appreciation or thanks.
Grateful => "grateful",
/// In the mood for flirting.
#[xml(name = "flirtatious")]
Flirtatious,
/// Feeling very sad about something, especially something lost; mournful; sorrowful.
Grieving => "grieving",
/// Suffering from frustration; dissatisfied, agitated, or discontented because one is unable to perform an action or fulfill a desire.
#[xml(name = "frustrated")]
Frustrated,
/// Unhappy and irritable.
Grumpy => "grumpy",
/// Feeling appreciation or thanks.
#[xml(name = "grateful")]
Grateful,
/// Feeling responsible for wrongdoing; feeling blameworthy.
Guilty => "guilty",
/// Feeling very sad about something, especially something lost; mournful; sorrowful.
#[xml(name = "grieving")]
Grieving,
/// Experiencing the effect of favourable fortune; having the feeling arising from the consciousness of well-being or of enjoyment; enjoying good of any kind, as peace, tranquillity, comfort; contented; joyous.
Happy => "happy",
/// Unhappy and irritable.
#[xml(name = "grumpy")]
Grumpy,
/// Having a positive feeling, belief, or expectation that something wished for can or will happen.
Hopeful => "hopeful",
/// Feeling responsible for wrongdoing; feeling blameworthy.
#[xml(name = "guilty")]
Guilty,
/// Feeling the sensation of heat, especially to the point of discomfort.
Hot => "hot",
/// Experiencing the effect of favourable fortune; having the feeling arising from the consciousness of well-being or of enjoyment; enjoying good of any kind, as peace, tranquillity, comfort; contented; joyous.
#[xml(name = "happy")]
Happy,
/// Having or showing a modest or low estimate of one's own importance; feeling lowered in dignity or importance.
Humbled => "humbled",
/// Having a positive feeling, belief, or expectation that something wished for can or will happen.
#[xml(name = "hopeful")]
Hopeful,
/// Feeling deprived of dignity or self-respect.
Humiliated => "humiliated",
/// Feeling the sensation of heat, especially to the point of discomfort.
#[xml(name = "hot")]
Hot,
/// Having a physical need for food.
Hungry => "hungry",
/// Having or showing a modest or low estimate of one's own importance; feeling lowered in dignity or importance.
#[xml(name = "humbled")]
Humbled,
/// Wounded, injured, or pained, whether physically or emotionally.
Hurt => "hurt",
/// Feeling deprived of dignity or self-respect.
#[xml(name = "humiliated")]
Humiliated,
/// Favourably affected by something or someone.
Impressed => "impressed",
/// Having a physical need for food.
#[xml(name = "hungry")]
Hungry,
/// Feeling amazement at something or someone; or feeling a combination of fear and reverence.
InAwe => "in_awe",
/// Wounded, injured, or pained, whether physically or emotionally.
#[xml(name = "hurt")]
Hurt,
/// Feeling strong affection, care, liking, or attraction..
InLove => "in_love",
/// Favourably affected by something or someone.
#[xml(name = "impressed")]
Impressed,
/// Showing anger or indignation, especially at something unjust or wrong.
Indignant => "indignant",
/// Feeling amazement at something or someone; or feeling a combination of fear and reverence.
#[xml(name = "in_awe")]
InAwe,
/// Showing great attention to something or someone; having or showing interest.
Interested => "interested",
/// Feeling strong affection, care, liking, or attraction..
#[xml(name = "in_love")]
InLove,
/// Under the influence of alcohol; drunk.
Intoxicated => "intoxicated",
/// Showing anger or indignation, especially at something unjust or wrong.
#[xml(name = "indignant")]
Indignant,
/// Feeling as if one cannot be defeated, overcome or denied.
Invincible => "invincible",
/// Showing great attention to something or someone; having or showing interest.
#[xml(name = "interested")]
Interested,
/// Fearful of being replaced in position or affection.
Jealous => "jealous",
/// Under the influence of alcohol; drunk.
#[xml(name = "intoxicated")]
Intoxicated,
/// Feeling isolated, empty, or abandoned.
Lonely => "lonely",
/// Feeling as if one cannot be defeated, overcome or denied.
#[xml(name = "invincible")]
Invincible,
/// Unable to find one's way, either physically or emotionally.
Lost => "lost",
/// Fearful of being replaced in position or affection.
#[xml(name = "jealous")]
Jealous,
/// Feeling as if one will be favored by luck.
Lucky => "lucky",
/// Feeling isolated, empty, or abandoned.
#[xml(name = "lonely")]
Lonely,
/// Causing or intending to cause intentional harm; bearing ill will towards another; cruel; malicious.
Mean => "mean",
/// Unable to find one's way, either physically or emotionally.
#[xml(name = "lost")]
Lost,
/// Given to sudden or frequent changes of mind or feeling; temperamental.
Moody => "moody",
/// Feeling as if one will be favored by luck.
#[xml(name = "lucky")]
Lucky,
/// Easily agitated or alarmed; apprehensive or anxious.
Nervous => "nervous",
/// Causing or intending to cause intentional harm; bearing ill will towards another; cruel; malicious.
#[xml(name = "mean")]
Mean,
/// Not having a strong mood or emotional state.
Neutral => "neutral",
/// Given to sudden or frequent changes of mind or feeling; temperamental.
#[xml(name = "moody")]
Moody,
/// Feeling emotionally hurt, displeased, or insulted.
Offended => "offended",
/// Easily agitated or alarmed; apprehensive or anxious.
#[xml(name = "nervous")]
Nervous,
/// Feeling resentful anger caused by an extremely violent or vicious attack, or by an offensive, immoral, or indecent act.
Outraged => "outraged",
/// Not having a strong mood or emotional state.
#[xml(name = "neutral")]
Neutral,
/// Interested in play; fun, recreational, unserious, lighthearted; joking, silly.
Playful => "playful",
/// Feeling emotionally hurt, displeased, or insulted.
#[xml(name = "offended")]
Offended,
/// Feeling a sense of one's own worth or accomplishment.
Proud => "proud",
/// Feeling resentful anger caused by an extremely violent or vicious attack, or by an offensive, immoral, or indecent act.
#[xml(name = "outraged")]
Outraged,
/// Having an easy-going mood; not stressed; calm.
Relaxed => "relaxed",
/// Interested in play; fun, recreational, unserious, lighthearted; joking, silly.
#[xml(name = "playful")]
Playful,
/// Feeling uplifted because of the removal of stress or discomfort.
Relieved => "relieved",
/// Feeling a sense of one's own worth or accomplishment.
#[xml(name = "proud")]
Proud,
/// Feeling regret or sadness for doing something wrong.
Remorseful => "remorseful",
/// Having an easy-going mood; not stressed; calm.
#[xml(name = "relaxed")]
Relaxed,
/// Without rest; unable to be still or quiet; uneasy; continually moving.
Restless => "restless",
/// Feeling uplifted because of the removal of stress or discomfort.
#[xml(name = "relieved")]
Relieved,
/// Feeling sorrow; sorrowful, mournful.
Sad => "sad",
/// Feeling regret or sadness for doing something wrong.
#[xml(name = "remorseful")]
Remorseful,
/// Mocking and ironical.
Sarcastic => "sarcastic",
/// Without rest; unable to be still or quiet; uneasy; continually moving.
#[xml(name = "restless")]
Restless,
/// Pleased at the fulfillment of a need or desire.
Satisfied => "satisfied",
/// Feeling sorrow; sorrowful, mournful.
#[xml(name = "sad")]
Sad,
/// Without humor or expression of happiness; grave in manner or disposition; earnest; thoughtful; solemn.
Serious => "serious",
/// Mocking and ironical.
#[xml(name = "sarcastic")]
Sarcastic,
/// Surprised, startled, confused, or taken aback.
Shocked => "shocked",
/// Pleased at the fulfillment of a need or desire.
#[xml(name = "satisfied")]
Satisfied,
/// Feeling easily frightened or scared; timid; reserved or coy.
Shy => "shy",
/// Without humor or expression of happiness; grave in manner or disposition; earnest; thoughtful; solemn.
#[xml(name = "serious")]
Serious,
/// Feeling in poor health; ill.
Sick => "sick",
/// Surprised, startled, confused, or taken aback.
#[xml(name = "shocked")]
Shocked,
/// Feeling the need for sleep.
Sleepy => "sleepy",
/// Feeling easily frightened or scared; timid; reserved or coy.
#[xml(name = "shy")]
Shy,
/// Acting without planning; natural; impulsive.
Spontaneous => "spontaneous",
/// Feeling in poor health; ill.
#[xml(name = "sick")]
Sick,
/// Suffering emotional pressure.
Stressed => "stressed",
/// Feeling the need for sleep.
#[xml(name = "sleepy")]
Sleepy,
/// Capable of producing great physical force; or, emotionally forceful, able, determined, unyielding.
Strong => "strong",
/// Acting without planning; natural; impulsive.
#[xml(name = "spontaneous")]
Spontaneous,
/// Experiencing a feeling caused by something unexpected.
Surprised => "surprised",
/// Suffering emotional pressure.
#[xml(name = "stressed")]
Stressed,
/// Showing appreciation or gratitude.
Thankful => "thankful",
/// Capable of producing great physical force; or, emotionally forceful, able, determined, unyielding.
#[xml(name = "strong")]
Strong,
/// Feeling the need to drink.
Thirsty => "thirsty",
/// Experiencing a feeling caused by something unexpected.
#[xml(name = "surprised")]
Surprised,
/// In need of rest or sleep.
Tired => "tired",
/// Showing appreciation or gratitude.
#[xml(name = "thankful")]
Thankful,
/// [Feeling any emotion not defined here.]
Undefined => "undefined",
/// Feeling the need to drink.
#[xml(name = "thirsty")]
Thirsty,
/// Lacking in force or ability, either physical or emotional.
Weak => "weak",
/// In need of rest or sleep.
#[xml(name = "tired")]
Tired,
/// Thinking about unpleasant things that have happened or that might happen; feeling afraid and unhappy.
Worried => "worried",
}
);
/// [Feeling any emotion not defined here.]
#[xml(name = "undefined")]
Undefined,
/// Lacking in force or ability, either physical or emotional.
#[xml(name = "weak")]
Weak,
/// Thinking about unpleasant things that have happened or that might happen; feeling afraid and unhappy.
#[xml(name = "worried")]
Worried,
}
generate_elem_id!(
/// Free-form text description of the mood.

View file

@ -97,47 +97,58 @@ pub struct Success {
pub data: Vec<u8>,
}
generate_element_enum!(
/// List of possible failure conditions for SASL.
DefinedCondition, "defined-condition", SASL, {
/// The client aborted the authentication with
/// [abort](struct.Abort.html).
Aborted => "aborted",
/// List of possible failure conditions for SASL.
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::SASL, exhaustive)]
pub enum DefinedCondition {
/// The client aborted the authentication with
/// [abort](struct.Abort.html).
#[xml(name = "aborted")]
Aborted,
/// The account the client is trying to authenticate against has been
/// disabled.
AccountDisabled => "account-disabled",
/// The account the client is trying to authenticate against has been
/// disabled.
#[xml(name = "account-disabled")]
AccountDisabled,
/// The credentials for this account have expired.
CredentialsExpired => "credentials-expired",
/// The credentials for this account have expired.
#[xml(name = "credentials-expired")]
CredentialsExpired,
/// You must enable StartTLS or use direct TLS before using this
/// authentication mechanism.
EncryptionRequired => "encryption-required",
/// You must enable StartTLS or use direct TLS before using this
/// authentication mechanism.
#[xml(name = "encryption-required")]
EncryptionRequired,
/// The base64 data sent by the client is invalid.
IncorrectEncoding => "incorrect-encoding",
/// The base64 data sent by the client is invalid.
#[xml(name = "incorrect-encoding")]
IncorrectEncoding,
/// The authzid provided by the client is invalid.
InvalidAuthzid => "invalid-authzid",
/// The authzid provided by the client is invalid.
#[xml(name = "invalid-authzid")]
InvalidAuthzid,
/// The client tried to use an invalid mechanism, or none.
InvalidMechanism => "invalid-mechanism",
/// The client tried to use an invalid mechanism, or none.
#[xml(name = "invalid-mechanism")]
InvalidMechanism,
/// The client sent a bad request.
MalformedRequest => "malformed-request",
/// The client sent a bad request.
#[xml(name = "malformed-request")]
MalformedRequest,
/// The mechanism selected is weaker than what the server allows.
MechanismTooWeak => "mechanism-too-weak",
/// The mechanism selected is weaker than what the server allows.
#[xml(name = "mechanism-too-weak")]
MechanismTooWeak,
/// The credentials provided are invalid.
NotAuthorized => "not-authorized",
/// The credentials provided are invalid.
#[xml(name = "not-authorized")]
NotAuthorized,
/// The server encountered an issue which may be fixed later, the
/// client should retry at some point.
TemporaryAuthFailure => "temporary-auth-failure",
}
);
/// The server encountered an issue which may be fixed later, the
/// client should retry at some point.
#[xml(name = "temporary-auth-failure")]
TemporaryAuthFailure,
}
type Lang = String;

View file

@ -159,7 +159,7 @@ mod tests {
assert_size!(Enable, 12);
assert_size!(StreamId, 12);
assert_size!(Enabled, 36);
assert_size!(Failed, 12);
assert_size!(Failed, 24);
assert_size!(R, 0);
assert_size!(Resume, 16);
assert_size!(Resumed, 16);
@ -174,7 +174,7 @@ mod tests {
assert_size!(Enable, 12);
assert_size!(StreamId, 24);
assert_size!(Enabled, 64);
assert_size!(Failed, 12);
assert_size!(Failed, 40);
assert_size!(R, 0);
assert_size!(Resume, 32);
assert_size!(Resumed, 32);

View file

@ -4,12 +4,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{text::EmptyAsNone, AsXml, FromXml};
use crate::message::MessagePayload;
use crate::ns;
use crate::presence::PresencePayload;
use jid::Jid;
use minidom::Element;
use minidom::Node;
use std::collections::BTreeMap;
use std::convert::TryFrom;
use xso::error::{Error, FromElementError};
@ -34,163 +35,195 @@ generate_attribute!(
}
);
generate_element_enum!(
/// List of valid error conditions.
DefinedCondition, "condition", XMPP_STANZAS, {
/// The sender has sent a stanza containing XML that does not conform
/// to the appropriate schema or that cannot be processed (e.g., an IQ
/// stanza that includes an unrecognized value of the 'type' attribute,
/// or an element that is qualified by a recognized namespace but that
/// violates the defined syntax for the element); the associated error
/// type SHOULD be "modify".
BadRequest => "bad-request",
/// List of valid error conditions.
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::XMPP_STANZAS, exhaustive)]
pub enum DefinedCondition {
/// The sender has sent a stanza containing XML that does not conform
/// to the appropriate schema or that cannot be processed (e.g., an IQ
/// stanza that includes an unrecognized value of the 'type' attribute,
/// or an element that is qualified by a recognized namespace but that
/// violates the defined syntax for the element); the associated error
/// type SHOULD be "modify".
#[xml(name = "bad-request")]
BadRequest,
/// Access cannot be granted because an existing resource exists with
/// the same name or address; the associated error type SHOULD be
/// "cancel".
Conflict => "conflict",
/// Access cannot be granted because an existing resource exists with
/// the same name or address; the associated error type SHOULD be
/// "cancel".
#[xml(name = "conflict")]
Conflict,
/// The feature represented in the XML stanza is not implemented by the
/// intended recipient or an intermediate server and therefore the
/// stanza cannot be processed (e.g., the entity understands the
/// namespace but does not recognize the element name); the associated
/// error type SHOULD be "cancel" or "modify".
FeatureNotImplemented => "feature-not-implemented",
/// The feature represented in the XML stanza is not implemented by the
/// intended recipient or an intermediate server and therefore the
/// stanza cannot be processed (e.g., the entity understands the
/// namespace but does not recognize the element name); the associated
/// error type SHOULD be "cancel" or "modify".
#[xml(name = "feature-not-implemented")]
FeatureNotImplemented,
/// The requesting entity does not possess the necessary permissions to
/// perform an action that only certain authorized roles or individuals
/// are allowed to complete (i.e., it typically relates to
/// authorization rather than authentication); the associated error
/// type SHOULD be "auth".
Forbidden => "forbidden",
/// The requesting entity does not possess the necessary permissions to
/// perform an action that only certain authorized roles or individuals
/// are allowed to complete (i.e., it typically relates to
/// authorization rather than authentication); the associated error
/// type SHOULD be "auth".
#[xml(name = "forbidden")]
Forbidden,
/// The recipient or server can no longer be contacted at this address,
/// typically on a permanent basis (as opposed to the \<redirect/\> error
/// condition, which is used for temporary addressing failures); the
/// associated error type SHOULD be "cancel" and the error stanza
/// SHOULD include a new address (if available) as the XML character
/// data of the \<gone/\> element (which MUST be a Uniform Resource
/// Identifier (URI) or Internationalized Resource Identifier (IRI) at
/// which the entity can be contacted, typically an XMPP IRI as
/// specified in [XMPPURI](https://www.rfc-editor.org/rfc/rfc5122)).
Gone => "gone",
/// The recipient or server can no longer be contacted at this address,
/// typically on a permanent basis (as opposed to the \<redirect/\> error
/// condition, which is used for temporary addressing failures); the
/// associated error type SHOULD be "cancel" and the error stanza
/// SHOULD include a new address (if available) as the XML character
/// data of the \<gone/\> element (which MUST be a Uniform Resource
/// Identifier (URI) or Internationalized Resource Identifier (IRI) at
/// which the entity can be contacted, typically an XMPP IRI as
/// specified in [XMPPURI](https://www.rfc-editor.org/rfc/rfc5122)).
#[xml(name = "gone")]
Gone {
/// The new address of the entity for which the error was returned,
/// if available.
#[xml(text(codec = EmptyAsNone))]
new_address: Option<String>,
},
/// The server has experienced a misconfiguration or other internal
/// error that prevents it from processing the stanza; the associated
/// error type SHOULD be "cancel".
InternalServerError => "internal-server-error",
/// The server has experienced a misconfiguration or other internal
/// error that prevents it from processing the stanza; the associated
/// error type SHOULD be "cancel".
#[xml(name = "internal-server-error")]
InternalServerError,
/// The addressed JID or item requested cannot be found; the associated
/// error type SHOULD be "cancel".
ItemNotFound => "item-not-found",
/// The addressed JID or item requested cannot be found; the associated
/// error type SHOULD be "cancel".
#[xml(name = "item-not-found")]
ItemNotFound,
/// The sending entity has provided (e.g., during resource binding) or
/// communicated (e.g., in the 'to' address of a stanza) an XMPP
/// address or aspect thereof that violates the rules defined in
/// [XMPPADDR]; the associated error type SHOULD be "modify".
JidMalformed => "jid-malformed",
/// The sending entity has provided (e.g., during resource binding) or
/// communicated (e.g., in the 'to' address of a stanza) an XMPP
/// address or aspect thereof that violates the rules defined in
/// [XMPPADDR]; the associated error type SHOULD be "modify".
#[xml(name = "jid-malformed")]
JidMalformed,
/// The recipient or server understands the request but cannot process
/// it because the request does not meet criteria defined by the
/// recipient or server (e.g., a request to subscribe to information
/// that does not simultaneously include configuration parameters
/// needed by the recipient); the associated error type SHOULD be
/// "modify".
NotAcceptable => "not-acceptable",
/// The recipient or server understands the request but cannot process
/// it because the request does not meet criteria defined by the
/// recipient or server (e.g., a request to subscribe to information
/// that does not simultaneously include configuration parameters
/// needed by the recipient); the associated error type SHOULD be
/// "modify".
#[xml(name = "not-acceptable")]
NotAcceptable,
/// The recipient or server does not allow any entity to perform the
/// action (e.g., sending to entities at a blacklisted domain); the
/// associated error type SHOULD be "cancel".
NotAllowed => "not-allowed",
/// The recipient or server does not allow any entity to perform the
/// action (e.g., sending to entities at a blacklisted domain); the
/// associated error type SHOULD be "cancel".
#[xml(name = "not-allowed")]
NotAllowed,
/// The sender needs to provide credentials before being allowed to
/// perform the action, or has provided improper credentials (the name
/// "not-authorized", which was borrowed from the "401 Unauthorized"
/// error of HTTP, might lead the reader to think that this condition
/// relates to authorization, but instead it is typically used in
/// relation to authentication); the associated error type SHOULD be
/// "auth".
NotAuthorized => "not-authorized",
/// The sender needs to provide credentials before being allowed to
/// perform the action, or has provided improper credentials (the name
/// "not-authorized", which was borrowed from the "401 Unauthorized"
/// error of HTTP, might lead the reader to think that this condition
/// relates to authorization, but instead it is typically used in
/// relation to authentication); the associated error type SHOULD be
/// "auth".
#[xml(name = "not-authorized")]
NotAuthorized,
/// The entity has violated some local service policy (e.g., a message
/// contains words that are prohibited by the service) and the server
/// MAY choose to specify the policy in the \<text/\> element or in an
/// application-specific condition element; the associated error type
/// SHOULD be "modify" or "wait" depending on the policy being
/// violated.
PolicyViolation => "policy-violation",
/// The entity has violated some local service policy (e.g., a message
/// contains words that are prohibited by the service) and the server
/// MAY choose to specify the policy in the \<text/\> element or in an
/// application-specific condition element; the associated error type
/// SHOULD be "modify" or "wait" depending on the policy being
/// violated.
#[xml(name = "policy-violation")]
PolicyViolation,
/// The intended recipient is temporarily unavailable, undergoing
/// maintenance, etc.; the associated error type SHOULD be "wait".
RecipientUnavailable => "recipient-unavailable",
/// The intended recipient is temporarily unavailable, undergoing
/// maintenance, etc.; the associated error type SHOULD be "wait".
#[xml(name = "recipient-unavailable")]
RecipientUnavailable,
/// The recipient or server is redirecting requests for this
/// information to another entity, typically in a temporary fashion (as
/// opposed to the \<gone/\> error condition, which is used for permanent
/// addressing failures); the associated error type SHOULD be "modify"
/// and the error stanza SHOULD contain the alternate address in the
/// XML character data of the \<redirect/\> element (which MUST be a URI
/// or IRI with which the sender can communicate, typically an XMPP IRI
/// as specified in [XMPPURI](https://xmpp.org/rfcs/rfc5122.html)).
Redirect => "redirect",
/// The recipient or server is redirecting requests for this
/// information to another entity, typically in a temporary fashion (as
/// opposed to the \<gone/\> error condition, which is used for permanent
/// addressing failures); the associated error type SHOULD be "modify"
/// and the error stanza SHOULD contain the alternate address in the
/// XML character data of the \<redirect/\> element (which MUST be a URI
/// or IRI with which the sender can communicate, typically an XMPP IRI
/// as specified in [XMPPURI](https://xmpp.org/rfcs/rfc5122.html)).
#[xml(name = "redirect")]
Redirect {
/// The new address of the entity for which the error was returned,
/// if available.
#[xml(text(codec = EmptyAsNone))]
new_address: Option<String>,
},
/// The requesting entity is not authorized to access the requested
/// service because prior registration is necessary (examples of prior
/// registration include members-only rooms in XMPP multi-user chat
/// [XEP0045] and gateways to non-XMPP instant messaging services,
/// which traditionally required registration in order to use the
/// gateway [XEP0100]); the associated error type SHOULD be "auth".
RegistrationRequired => "registration-required",
/// The requesting entity is not authorized to access the requested
/// service because prior registration is necessary (examples of prior
/// registration include members-only rooms in XMPP multi-user chat
/// [XEP0045] and gateways to non-XMPP instant messaging services,
/// which traditionally required registration in order to use the
/// gateway [XEP0100]); the associated error type SHOULD be "auth".
#[xml(name = "registration-required")]
RegistrationRequired,
/// A remote server or service specified as part or all of the JID of
/// the intended recipient does not exist or cannot be resolved (e.g.,
/// there is no _xmpp-server._tcp DNS SRV record, the A or AAAA
/// fallback resolution fails, or A/AAAA lookups succeed but there is
/// no response on the IANA-registered port 5269); the associated error
/// type SHOULD be "cancel".
RemoteServerNotFound => "remote-server-not-found",
/// A remote server or service specified as part or all of the JID of
/// the intended recipient does not exist or cannot be resolved (e.g.,
/// there is no _xmpp-server._tcp DNS SRV record, the A or AAAA
/// fallback resolution fails, or A/AAAA lookups succeed but there is
/// no response on the IANA-registered port 5269); the associated error
/// type SHOULD be "cancel".
#[xml(name = "remote-server-not-found")]
RemoteServerNotFound,
/// A remote server or service specified as part or all of the JID of
/// the intended recipient (or needed to fulfill a request) was
/// resolved but communications could not be established within a
/// reasonable amount of time (e.g., an XML stream cannot be
/// established at the resolved IP address and port, or an XML stream
/// can be established but stream negotiation fails because of problems
/// with TLS, SASL, Server Dialback, etc.); the associated error type
/// SHOULD be "wait" (unless the error is of a more permanent nature,
/// e.g., the remote server is found but it cannot be authenticated or
/// it violates security policies).
RemoteServerTimeout => "remote-server-timeout",
/// A remote server or service specified as part or all of the JID of
/// the intended recipient (or needed to fulfill a request) was
/// resolved but communications could not be established within a
/// reasonable amount of time (e.g., an XML stream cannot be
/// established at the resolved IP address and port, or an XML stream
/// can be established but stream negotiation fails because of problems
/// with TLS, SASL, Server Dialback, etc.); the associated error type
/// SHOULD be "wait" (unless the error is of a more permanent nature,
/// e.g., the remote server is found but it cannot be authenticated or
/// it violates security policies).
#[xml(name = "remote-server-timeout")]
RemoteServerTimeout,
/// The server or recipient is busy or lacks the system resources
/// necessary to service the request; the associated error type SHOULD
/// be "wait".
ResourceConstraint => "resource-constraint",
/// The server or recipient is busy or lacks the system resources
/// necessary to service the request; the associated error type SHOULD
/// be "wait".
#[xml(name = "resource-constraint")]
ResourceConstraint,
/// The server or recipient does not currently provide the requested
/// service; the associated error type SHOULD be "cancel".
ServiceUnavailable => "service-unavailable",
/// The server or recipient does not currently provide the requested
/// service; the associated error type SHOULD be "cancel".
#[xml(name = "service-unavailable")]
ServiceUnavailable,
/// The requesting entity is not authorized to access the requested
/// service because a prior subscription is necessary (examples of
/// prior subscription include authorization to receive presence
/// information as defined in [XMPPIM] and opt-in data feeds for XMPP
/// publish-subscribe as defined in [XEP0060]); the associated error
/// type SHOULD be "auth".
SubscriptionRequired => "subscription-required",
/// The requesting entity is not authorized to access the requested
/// service because a prior subscription is necessary (examples of
/// prior subscription include authorization to receive presence
/// information as defined in [XMPPIM] and opt-in data feeds for XMPP
/// publish-subscribe as defined in [XEP0060]); the associated error
/// type SHOULD be "auth".
#[xml(name = "subscription-required")]
SubscriptionRequired,
/// The error condition is not one of those defined by the other
/// conditions in this list; any error type can be associated with this
/// condition, and it SHOULD NOT be used except in conjunction with an
/// application-specific condition.
UndefinedCondition => "undefined-condition",
/// The error condition is not one of those defined by the other
/// conditions in this list; any error type can be associated with this
/// condition, and it SHOULD NOT be used except in conjunction with an
/// application-specific condition.
#[xml(name = "undefined-condition")]
UndefinedCondition,
/// The recipient or server understood the request but was not
/// expecting it at this time (e.g., the request was out of order); the
/// associated error type SHOULD be "wait" or "modify".
UnexpectedRequest => "unexpected-request",
}
);
/// The recipient or server understood the request but was not
/// expecting it at this time (e.g., the request was out of order); the
/// associated error type SHOULD be "wait" or "modify".
#[xml(name = "unexpected-request")]
UnexpectedRequest,
}
type Lang = String;
@ -211,11 +244,6 @@ pub struct StanzaError {
/// A protocol-specific extension for this error.
pub other: Option<Element>,
/// May include an alternate address if `defined_condition` is `Gone` or `Redirect`. It is
/// a Uniform Resource Identifier [URI] or Internationalized Resource Identifier [IRI] at
/// which the entity can be contacted, typically an XMPP IRI as specified in [XMPPURI]
pub alternate_address: Option<String>,
}
impl MessagePayload for StanzaError {}
@ -243,7 +271,6 @@ impl StanzaError {
map
},
other: None,
alternate_address: None,
}
}
}
@ -263,7 +290,6 @@ impl TryFrom<Element> for StanzaError {
defined_condition: DefinedCondition::UndefinedCondition,
texts: BTreeMap::new(),
other: None,
alternate_address: None,
};
let mut defined_condition = None;
@ -286,16 +312,7 @@ impl TryFrom<Element> for StanzaError {
}
check_no_children!(child, "defined-condition");
check_no_attributes!(child, "defined-condition");
let condition = DefinedCondition::try_from(child.clone())?;
if condition == DefinedCondition::Gone || condition == DefinedCondition::Redirect {
stanza_error.alternate_address = child.nodes().find_map(|node| {
let Node::Text(text) = node else { return None };
Some(text.to_string())
});
}
defined_condition = Some(condition);
defined_condition = Some(DefinedCondition::try_from(child.clone())?);
} else {
if stanza_error.other.is_some() {
return Err(
@ -336,16 +353,16 @@ mod tests {
#[test]
fn test_size() {
assert_size!(ErrorType, 1);
assert_size!(DefinedCondition, 1);
assert_size!(StanzaError, 104);
assert_size!(DefinedCondition, 16);
assert_size!(StanzaError, 108);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_size() {
assert_size!(ErrorType, 1);
assert_size!(DefinedCondition, 1);
assert_size!(StanzaError, 208);
assert_size!(DefinedCondition, 32);
assert_size!(StanzaError, 216);
}
#[test]
@ -446,10 +463,11 @@ mod tests {
.unwrap();
let error = StanzaError::try_from(elem).unwrap();
assert_eq!(error.type_, ErrorType::Cancel);
assert_eq!(error.defined_condition, DefinedCondition::Gone);
assert_eq!(
error.alternate_address,
Some("xmpp:room@muc.example.org?join".to_string())
error.defined_condition,
DefinedCondition::Gone {
new_address: Some("xmpp:room@muc.example.org?join".to_string()),
}
);
}
@ -465,8 +483,10 @@ mod tests {
.unwrap();
let error = StanzaError::try_from(elem).unwrap();
assert_eq!(error.type_, ErrorType::Cancel);
assert_eq!(error.defined_condition, DefinedCondition::Gone);
assert_eq!(error.alternate_address, None);
assert_eq!(
error.defined_condition,
DefinedCondition::Gone { new_address: None }
);
}
#[test]
@ -481,10 +501,11 @@ mod tests {
.unwrap();
let error = StanzaError::try_from(elem).unwrap();
assert_eq!(error.type_, ErrorType::Modify);
assert_eq!(error.defined_condition, DefinedCondition::Redirect);
assert_eq!(
error.alternate_address,
Some("xmpp:characters@conference.example.org".to_string())
error.defined_condition,
DefinedCondition::Redirect {
new_address: Some("xmpp:characters@conference.example.org".to_string()),
}
);
}
@ -500,7 +521,9 @@ mod tests {
.unwrap();
let error = StanzaError::try_from(elem).unwrap();
assert_eq!(error.type_, ErrorType::Modify);
assert_eq!(error.defined_condition, DefinedCondition::Redirect);
assert_eq!(error.alternate_address, None);
assert_eq!(
error.defined_condition,
DefinedCondition::Redirect { new_address: None }
);
}
}