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?
11#[derive(Debug)]
12pub struct StreamFeatures(pub Element);
13
14impl StreamFeatures {
15 /// Wrap the nonza
16 pub fn new(element: Element) -> Self {
17 StreamFeatures(element)
18 }
19
20 /// Can initiate TLS session with this server?
21 pub fn can_starttls(&self) -> bool {
22 self.0.get_child("starttls", ns::TLS).is_some()
23 }
24
25 /// Iterate over SASL mechanisms
26 pub fn sasl_mechanisms<'a>(&'a self) -> Result<impl Iterator<Item = String> + 'a, AuthError> {
27 Ok(self
28 .0
29 .get_child("mechanisms", ns::SASL)
30 .ok_or(AuthError::NoMechanism)?
31 .children()
32 .filter(|child| child.is("mechanism", ns::SASL))
33 .map(|mech_el| mech_el.text()))
34 }
35
36 /// Does server support user resource binding?
37 pub fn can_bind(&self) -> bool {
38 self.0.get_child("bind", ns::BIND).is_some()
39 }
40}