1use ns;
2use minidom::Element;
3use util::{FromElement, FromParentElement};
4use std::str::FromStr;
5
6#[derive(Copy, Clone, Debug)]
7pub enum ErrorType {
8 Auth,
9 Cancel,
10 Continue,
11 Modify,
12 Wait,
13}
14
15impl FromStr for ErrorType {
16 type Err = ();
17
18 fn from_str(s: &str) -> Result<ErrorType, ()> {
19 Ok(match s {
20 "auth" => ErrorType::Auth,
21 "cancel" => ErrorType::Cancel,
22 "continue" => ErrorType::Continue,
23 "modify" => ErrorType::Modify,
24 "wait" => ErrorType::Wait,
25 _ => { return Err(()); },
26 })
27 }
28}
29
30#[derive(Clone, Debug)]
31pub enum Condition {
32 BadRequest,
33 Conflict,
34 FeatureNotImplemented,
35 Forbidden,
36 Gone(Option<String>),
37 InternalServerError,
38 ItemNotFound,
39 JidMalformed,
40 NotAcceptable,
41 NotAllowed,
42 NotAuthorized,
43 PolicyViolation,
44 RecipientUnavailable,
45 Redirect(Option<String>),
46 RegistrationRequired,
47 RemoteServerNotFound,
48 RemoteServerTimeout,
49 ResourceConstraint,
50 ServiceUnavailable,
51 SubscriptionRequired,
52 UndefinedCondition,
53 UnexpectedRequest,
54}
55
56impl FromParentElement for Condition {
57 type Err = ();
58
59 fn from_parent_element(elem: &Element) -> Result<Condition, ()> {
60 if elem.has_child("bad-request", ns::STANZAS) {
61 Ok(Condition::BadRequest)
62 }
63 else if elem.has_child("conflict", ns::STANZAS) {
64 Ok(Condition::Conflict)
65 }
66 else if elem.has_child("feature-not-implemented", ns::STANZAS) {
67 Ok(Condition::FeatureNotImplemented)
68 }
69 else if elem.has_child("forbidden", ns::STANZAS) {
70 Ok(Condition::Forbidden)
71 }
72 else if let Some(alt) = elem.get_child("gone", ns::STANZAS) {
73 let text = alt.text();
74 let inner = if text == "" { None } else { Some(text) };
75 Ok(Condition::Gone(inner))
76 }
77 else if elem.has_child("internal-server-error", ns::STANZAS) {
78 Ok(Condition::InternalServerError)
79 }
80 else if elem.has_child("item-not-found", ns::STANZAS) {
81 Ok(Condition::ItemNotFound)
82 }
83 else if elem.has_child("jid-malformed", ns::STANZAS) {
84 Ok(Condition::JidMalformed)
85 }
86 else if elem.has_child("not-acceptable", ns::STANZAS) {
87 Ok(Condition::NotAcceptable)
88 }
89 else if elem.has_child("not-allowed", ns::STANZAS) {
90 Ok(Condition::NotAllowed)
91 }
92 else if elem.has_child("not-authorized", ns::STANZAS) {
93 Ok(Condition::NotAuthorized)
94 }
95 else if elem.has_child("policy-violation", ns::STANZAS) {
96 Ok(Condition::PolicyViolation)
97 }
98 else if elem.has_child("recipient-unavailable", ns::STANZAS) {
99 Ok(Condition::RecipientUnavailable)
100 }
101 else if let Some(alt) = elem.get_child("redirect", ns::STANZAS) {
102 let text = alt.text();
103 let inner = if text == "" { None } else { Some(text) };
104 Ok(Condition::Redirect(inner))
105 }
106 else if elem.has_child("registration-required", ns::STANZAS) {
107 Ok(Condition::RegistrationRequired)
108 }
109 else if elem.has_child("remote-server-not-found", ns::STANZAS) {
110 Ok(Condition::RemoteServerNotFound)
111 }
112 else if elem.has_child("remote-server-timeout", ns::STANZAS) {
113 Ok(Condition::RemoteServerTimeout)
114 }
115 else if elem.has_child("resource-constraint", ns::STANZAS) {
116 Ok(Condition::ResourceConstraint)
117 }
118 else if elem.has_child("service-unavailable", ns::STANZAS) {
119 Ok(Condition::ServiceUnavailable)
120 }
121 else if elem.has_child("subscription-required", ns::STANZAS) {
122 Ok(Condition::SubscriptionRequired)
123 }
124 else if elem.has_child("undefined-condition", ns::STANZAS) {
125 Ok(Condition::UndefinedCondition)
126 }
127 else if elem.has_child("unexpected-request", ns::STANZAS) {
128 Ok(Condition::UnexpectedRequest)
129 }
130 else {
131 Err(())
132 }
133 }
134}
135
136#[derive(Clone, Debug)]
137pub struct StanzaError {
138 error_type: ErrorType,
139 text: Option<String>,
140 condition: Condition,
141}
142
143impl StanzaError {
144 pub fn new(error_type: ErrorType, text: Option<String>, condition: Condition) -> StanzaError {
145 StanzaError {
146 error_type: error_type,
147 text: text,
148 condition: condition,
149 }
150 }
151}
152
153impl FromElement for StanzaError {
154 type Err = ();
155
156 fn from_element(elem: &Element) -> Result<StanzaError, ()> {
157 if elem.is("error", ns::STANZAS) {
158 let error_type = elem.attr("type").ok_or(())?;
159 let err: ErrorType = error_type.parse().map_err(|_| ())?;
160 let condition: Condition = Condition::from_parent_element(elem)?;
161 let text = elem.get_child("text", ns::STANZAS).map(|c| c.text());
162 Ok(StanzaError {
163 error_type: err,
164 text: text,
165 condition: condition,
166 })
167 }
168 else {
169 Err(())
170 }
171 }
172}