xmpp-parsers: Make DiscoInfoResult::features a BTreeSet
Features must never be duplicated, so we can use a BTreeSet instead of a Vec to be nicer for users. It makes the internal API for computing caps and ecaps2 a bit worse, because it was expecting a slice directly, so for now let’s collect the BTreeSet into a Vec when computing the thing. A refactor to use Iterator might make it better eventually, but I won’t work on that before profiling it.
This commit is contained in:
parent
946d96d7c8
commit
bc88134c41
6 changed files with 20 additions and 9 deletions
|
|
@ -13,7 +13,8 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
|
||||||
- Remove the unnecessary SaslMechanisms struct, to directly extract
|
- Remove the unnecessary SaslMechanisms struct, to directly extract
|
||||||
SASL mechanisms in a Vec<String> in StreamFeatures.
|
SASL mechanisms in a Vec<String> in StreamFeatures.
|
||||||
- The type of disco::DiscoInfoResult::features changed from
|
- The type of disco::DiscoInfoResult::features changed from
|
||||||
Vec<Feature> to Vec<String>, this lets us remove Feature as well.
|
Vec<Feature> to BTreeSet<String>, this lets us remove Feature as
|
||||||
|
well.
|
||||||
- bind::BindFeature::required is now a bool, thanks to xso’s flag.
|
- bind::BindFeature::required is now a bool, thanks to xso’s flag.
|
||||||
- jingle_rtp::Description::rtcp_mux is now a bool flag too.
|
- jingle_rtp::Description::rtcp_mux is now a bool flag too.
|
||||||
- stream_limits::Limits now extract directly to NonZeroU32.
|
- stream_limits::Limits now extract directly to NonZeroU32.
|
||||||
|
|
|
||||||
|
|
@ -125,8 +125,11 @@ fn compute_extensions(extensions: &[DataForm]) -> Vec<u8> {
|
||||||
/// [ecaps2](../ecaps2/index.html) instead, see [this
|
/// [ecaps2](../ecaps2/index.html) instead, see [this
|
||||||
/// email](https://mail.jabber.org/pipermail/security/2009-July/000812.html).
|
/// email](https://mail.jabber.org/pipermail/security/2009-July/000812.html).
|
||||||
pub fn compute_disco(disco: &DiscoInfoResult) -> Vec<u8> {
|
pub fn compute_disco(disco: &DiscoInfoResult) -> Vec<u8> {
|
||||||
|
// TODO: Figure out a way to remove the clones here.
|
||||||
|
let features: Vec<_> = disco.features.iter().cloned().collect();
|
||||||
|
|
||||||
let identities_string = compute_identities(&disco.identities);
|
let identities_string = compute_identities(&disco.identities);
|
||||||
let features_string = compute_features(&disco.features);
|
let features_string = compute_features(&features);
|
||||||
let extensions_string = compute_extensions(&disco.extensions);
|
let extensions_string = compute_extensions(&disco.extensions);
|
||||||
|
|
||||||
let mut final_string = vec![];
|
let mut final_string = vec![];
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use crate::data_forms::DataForm;
|
||||||
use crate::iq::{IqGetPayload, IqResultPayload};
|
use crate::iq::{IqGetPayload, IqResultPayload};
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
use crate::rsm::{SetQuery, SetResult};
|
use crate::rsm::{SetQuery, SetResult};
|
||||||
|
use alloc::collections::BTreeSet;
|
||||||
use jid::Jid;
|
use jid::Jid;
|
||||||
|
|
||||||
/// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element.
|
/// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element.
|
||||||
|
|
@ -98,7 +99,7 @@ pub struct DiscoInfoResult {
|
||||||
|
|
||||||
/// List of features supported by this entity.
|
/// List of features supported by this entity.
|
||||||
#[xml(extract(n = .., name = "feature", fields(attribute(name = "var", type_ = String))))]
|
#[xml(extract(n = .., name = "feature", fields(attribute(name = "var", type_ = String))))]
|
||||||
pub features: Vec<String>,
|
pub features: BTreeSet<String>,
|
||||||
|
|
||||||
/// List of extensions reported by this entity.
|
/// List of extensions reported by this entity.
|
||||||
#[xml(child(n = ..))]
|
#[xml(child(n = ..))]
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,10 @@ fn compute_extensions(extensions: &[DataForm]) -> Result<Vec<u8>, Error> {
|
||||||
/// XEP-0390](https://xmpp.org/extensions/xep-0390.html#algorithm-input) on a
|
/// XEP-0390](https://xmpp.org/extensions/xep-0390.html#algorithm-input) on a
|
||||||
/// [disco#info query element](../disco/struct.DiscoInfoResult.html).
|
/// [disco#info query element](../disco/struct.DiscoInfoResult.html).
|
||||||
pub fn compute_disco(disco: &DiscoInfoResult) -> Result<Vec<u8>, Error> {
|
pub fn compute_disco(disco: &DiscoInfoResult) -> Result<Vec<u8>, Error> {
|
||||||
let features_string = compute_features(&disco.features);
|
// TODO: Figure out a way to remove the clones here.
|
||||||
|
let features: Vec<_> = disco.features.iter().cloned().collect();
|
||||||
|
|
||||||
|
let features_string = compute_features(&features);
|
||||||
let identities_string = compute_identities(&disco.identities);
|
let identities_string = compute_identities(&disco.identities);
|
||||||
let extensions_string = compute_extensions(&disco.extensions)?;
|
let extensions_string = compute_extensions(&disco.extensions)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::fs::{create_dir_all, File};
|
use std::fs::{create_dir_all, File};
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
|
|
@ -184,10 +185,10 @@ fn make_error(
|
||||||
|
|
||||||
fn make_disco() -> DiscoInfoResult {
|
fn make_disco() -> DiscoInfoResult {
|
||||||
let identities = vec![Identity::new("client", "bot", "en", "tokio-xmpp")];
|
let identities = vec![Identity::new("client", "bot", "en", "tokio-xmpp")];
|
||||||
let features = vec![
|
let features = BTreeSet::from([
|
||||||
String::from(ns::DISCO_INFO),
|
String::from(ns::DISCO_INFO),
|
||||||
format!("{}+notify", ns::AVATAR_METADATA),
|
format!("{}+notify", ns::AVATAR_METADATA),
|
||||||
];
|
]);
|
||||||
DiscoInfoResult {
|
DiscoInfoResult {
|
||||||
node: None,
|
node: None,
|
||||||
identities,
|
identities,
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts},
|
tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts},
|
||||||
};
|
};
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
pub struct ClientBuilder<'a, C: ServerConnector> {
|
pub struct ClientBuilder<'a, C: ServerConnector> {
|
||||||
jid: BareJid,
|
jid: BareJid,
|
||||||
|
|
@ -107,15 +108,16 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
|
||||||
"en",
|
"en",
|
||||||
self.config.disco.1.to_string(),
|
self.config.disco.1.to_string(),
|
||||||
)];
|
)];
|
||||||
let mut features = vec![String::from(ns::DISCO_INFO)];
|
let mut features = BTreeSet::new();
|
||||||
|
features.insert(String::from(ns::DISCO_INFO));
|
||||||
#[cfg(feature = "avatars")]
|
#[cfg(feature = "avatars")]
|
||||||
{
|
{
|
||||||
if self.features.contains(&ClientFeature::Avatars) {
|
if self.features.contains(&ClientFeature::Avatars) {
|
||||||
features.push(format!("{}+notify", ns::AVATAR_METADATA));
|
features.insert(format!("{}+notify", ns::AVATAR_METADATA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.features.contains(&ClientFeature::JoinRooms) {
|
if self.features.contains(&ClientFeature::JoinRooms) {
|
||||||
features.push(format!("{}+notify", ns::BOOKMARKS2));
|
features.insert(format!("{}+notify", ns::BOOKMARKS2));
|
||||||
}
|
}
|
||||||
DiscoInfoResult {
|
DiscoInfoResult {
|
||||||
node: None,
|
node: None,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue