From 6afd0ef52f658b240437e76c05a850ee85052ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Wed, 10 Jul 2024 16:38:00 +0200 Subject: [PATCH] parsers: port enums over to derive macros --- parsers/ChangeLog | 5 + parsers/src/chatstates.rs | 46 ++-- parsers/src/iq.rs | 8 +- parsers/src/mood.rs | 434 ++++++++++++++++++++++-------------- parsers/src/sasl.rs | 93 ++++---- parsers/src/sm.rs | 4 +- parsers/src/stanza_error.rs | 401 +++++++++++++++++---------------- 7 files changed, 563 insertions(+), 428 deletions(-) diff --git a/parsers/ChangeLog b/parsers/ChangeLog index 30ad6819094bfe9807ef39b3db35d11979412c6f..242fc2b9579508a1720d75fbbbbf35bc2fe46276 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -1,5 +1,10 @@ Version NEXT: XXXX-YY-ZZ RELEASER + * 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) diff --git a/parsers/src/chatstates.rs b/parsers/src/chatstates.rs index 8621317897aeb048c575eac480ce51915e9a718b..dbe2b3a1e4db33ee738f8dd737941f7c0d61f657 100644 --- a/parsers/src/chatstates.rs +++ b/parsers/src/chatstates.rs @@ -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 => "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 { + /// `` + #[xml(name = "active")] + Active, - /// `` - Composing => "composing", + /// `` + #[xml(name = "composing")] + Composing, - /// `` - Gone => "gone", + /// `` + #[xml(name = "gone")] + Gone, - /// `` - Inactive => "inactive", + /// `` + #[xml(name = "inactive")] + Inactive, - /// `` - Paused => "paused", - } -); + /// `` + #[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] diff --git a/parsers/src/iq.rs b/parsers/src/iq.rs index d2d4f272d10f5fe571e368da18a79fc2cace3f88..afd90a7cf3c1768feb5e11e3659710e57f623c76 100644 --- a/parsers/src/iq.rs +++ b/parsers/src/iq.rs @@ -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] diff --git a/parsers/src/mood.rs b/parsers/src/mood.rs index 9452072a45b32ea382d5d38c6339502f41ec7e3c..2ef31ec14d87799f719aabe2889581838c753c31 100644 --- a/parsers/src/mood.rs +++ b/parsers/src/mood.rs @@ -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. diff --git a/parsers/src/sasl.rs b/parsers/src/sasl.rs index cd46fd349917ad63fe3839be0f4fdc0dca3be2b1..1a330f6b2642efde43581934af7536d68bee6e04 100644 --- a/parsers/src/sasl.rs +++ b/parsers/src/sasl.rs @@ -97,47 +97,58 @@ pub struct Success { pub data: Vec, } -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", - - /// The account the client is trying to authenticate against has been - /// disabled. - AccountDisabled => "account-disabled", - - /// The credentials for this account have expired. - CredentialsExpired => "credentials-expired", - - /// You must enable StartTLS or use direct TLS before using this - /// authentication mechanism. - EncryptionRequired => "encryption-required", - - /// The base64 data sent by the client is invalid. - IncorrectEncoding => "incorrect-encoding", - - /// The authzid provided by the client is invalid. - InvalidAuthzid => "invalid-authzid", - - /// The client tried to use an invalid mechanism, or none. - InvalidMechanism => "invalid-mechanism", - - /// The client sent a bad request. - MalformedRequest => "malformed-request", - - /// The mechanism selected is weaker than what the server allows. - MechanismTooWeak => "mechanism-too-weak", - - /// The credentials provided are invalid. - NotAuthorized => "not-authorized", - - /// The server encountered an issue which may be fixed later, the - /// client should retry at some point. - TemporaryAuthFailure => "temporary-auth-failure", - } -); +/// 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. + #[xml(name = "account-disabled")] + AccountDisabled, + + /// 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. + #[xml(name = "encryption-required")] + EncryptionRequired, + + /// The base64 data sent by the client is invalid. + #[xml(name = "incorrect-encoding")] + IncorrectEncoding, + + /// The authzid provided by the client is invalid. + #[xml(name = "invalid-authzid")] + InvalidAuthzid, + + /// The client tried to use an invalid mechanism, or none. + #[xml(name = "invalid-mechanism")] + InvalidMechanism, + + /// The client sent a bad request. + #[xml(name = "malformed-request")] + MalformedRequest, + + /// The mechanism selected is weaker than what the server allows. + #[xml(name = "mechanism-too-weak")] + MechanismTooWeak, + + /// 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. + #[xml(name = "temporary-auth-failure")] + TemporaryAuthFailure, +} type Lang = String; diff --git a/parsers/src/sm.rs b/parsers/src/sm.rs index 10bbc0a3a5265b4bbcdd8883d549f2734e4d218a..59fbb955fd37193ac5ed6d97bfc5ef93d5ef616a 100644 --- a/parsers/src/sm.rs +++ b/parsers/src/sm.rs @@ -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); diff --git a/parsers/src/stanza_error.rs b/parsers/src/stanza_error.rs index 52e51a87989531027bcc8523da67b9ad8fbebade..55d26f4e519e2d010d83991c10b70379c0734051 100644 --- a/parsers/src/stanza_error.rs +++ b/parsers/src/stanza_error.rs @@ -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", - - /// Access cannot be granted because an existing resource exists with - /// the same name or address; the associated error type SHOULD be - /// "cancel". - 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 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 recipient or server can no longer be contacted at this address, - /// typically on a permanent basis (as opposed to the \ 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 \ 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 [XMPP‑URI](https://www.rfc-editor.org/rfc/rfc5122)). - Gone => "gone", - - /// 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 addressed JID or item requested cannot be found; the associated - /// error type SHOULD be "cancel". - ItemNotFound => "item-not-found", - - /// 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 - /// [XMPP‑ADDR]; the associated error type SHOULD be "modify". - JidMalformed => "jid-malformed", - - /// 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 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 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 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 \ 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 intended recipient is temporarily unavailable, undergoing - /// maintenance, etc.; the associated error type SHOULD be "wait". - RecipientUnavailable => "recipient-unavailable", - - /// The recipient or server is redirecting requests for this - /// information to another entity, typically in a temporary fashion (as - /// opposed to the \ 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 \ element (which MUST be a URI - /// or IRI with which the sender can communicate, typically an XMPP IRI - /// as specified in [XMPP‑URI](https://xmpp.org/rfcs/rfc5122.html)). - Redirect => "redirect", - - /// 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 - /// [XEP‑0045] and gateways to non-XMPP instant messaging services, - /// which traditionally required registration in order to use the - /// gateway [XEP‑0100]); the associated error type SHOULD be "auth". - RegistrationRequired => "registration-required", - - /// 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 (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", - - /// 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 does not currently provide the requested - /// service; the associated error type SHOULD be "cancel". - ServiceUnavailable => "service-unavailable", - - /// 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 [XMPP‑IM] and opt-in data feeds for XMPP - /// publish-subscribe as defined in [XEP‑0060]); the associated error - /// type SHOULD be "auth". - SubscriptionRequired => "subscription-required", - - /// 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 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", - } -); +/// 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". + #[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". + #[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". + #[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 \ 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 \ 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 [XMPP‑URI](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, + }, + + /// 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". + #[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 + /// [XMPP‑ADDR]; 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". + #[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". + #[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". + #[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 \ 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". + #[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 \ 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 \ element (which MUST be a URI + /// or IRI with which the sender can communicate, typically an XMPP IRI + /// as specified in [XMPP‑URI](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, + }, + + /// 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 + /// [XEP‑0045] and gateways to non-XMPP instant messaging services, + /// which traditionally required registration in order to use the + /// gateway [XEP‑0100]); 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". + #[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). + #[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". + #[xml(name = "resource-constraint")] + ResourceConstraint, + + /// 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 [XMPP‑IM] and opt-in data feeds for XMPP + /// publish-subscribe as defined in [XEP‑0060]); 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. + #[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". + #[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, - - /// 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 [XMPP‑URI] - pub alternate_address: Option, } impl MessagePayload for StanzaError {} @@ -243,7 +271,6 @@ impl StanzaError { map }, other: None, - alternate_address: None, } } } @@ -263,7 +290,6 @@ impl TryFrom 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 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 } + ); } }