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