1//! Contains wrapper for `<stream:features/>`
2
3use crate::error::AuthError;
4use xmpp_parsers::{ns, Element};
5
6/// Wraps `<stream:features/>`, usually the very first nonza of an
7/// XMPPStream.
8///
9/// TODO: should this rather go into xmpp-parsers, kept in a decoded
10/// struct?
11pub struct StreamFeatures(pub Element);
12
13impl StreamFeatures {
14 /// Wrap the nonza
15 pub fn new(element: Element) -> Self {
16 StreamFeatures(element)
17 }
18
19 /// Can initiate TLS session with this server?
20 pub fn can_starttls(&self) -> bool {
21 self.0.get_child("starttls", ns::TLS).is_some()
22 }
23
24 /// Iterate over SASL mechanisms
25 pub fn sasl_mechanisms<'a>(&'a self) -> Result<impl Iterator<Item = String> + 'a, AuthError> {
26 Ok(self
27 .0
28 .get_child("mechanisms", ns::SASL)
29 .ok_or(AuthError::NoMechanism)?
30 .children()
31 .filter(|child| child.is("mechanism", ns::SASL))
32 .map(|mech_el| mech_el.text()))
33 }
34
35 /// Does server support user resource binding?
36 pub fn can_bind(&self) -> bool {
37 self.0.get_child("bind", ns::BIND).is_some()
38 }
39}