xmpp-parsers: Remove Feature from disco#info
This was just a newtype for a String, but in general using it was harder than without it. This simplifies the public API.
This commit is contained in:
parent
d9f030c07e
commit
946d96d7c8
7 changed files with 23 additions and 40 deletions
|
|
@ -12,6 +12,8 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
|
||||||
used in XMPP.
|
used in XMPP.
|
||||||
- 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
|
||||||
|
Vec<Feature> to Vec<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.
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
use xso::{AsXml, FromXml};
|
use xso::{AsXml, FromXml};
|
||||||
|
|
||||||
use crate::data_forms::DataForm;
|
use crate::data_forms::DataForm;
|
||||||
use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity};
|
use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Identity};
|
||||||
use crate::hashes::{Algo, Hash};
|
use crate::hashes::{Algo, Hash};
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
use crate::presence::PresencePayload;
|
use crate::presence::PresencePayload;
|
||||||
|
|
@ -79,8 +79,8 @@ fn compute_items<T, F: Fn(&T) -> Vec<u8>>(things: &[T], encode: F) -> Vec<u8> {
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_features(features: &[Feature]) -> Vec<u8> {
|
fn compute_features(features: &[String]) -> Vec<u8> {
|
||||||
compute_items(features, |feature| compute_item(&feature.var))
|
compute_items(features, |feature| compute_item(&feature))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_identities(identities: &[Identity]) -> Vec<u8> {
|
fn compute_identities(identities: &[Identity]) -> Vec<u8> {
|
||||||
|
|
|
||||||
|
|
@ -26,22 +26,6 @@ pub struct DiscoInfoQuery {
|
||||||
|
|
||||||
impl IqGetPayload for DiscoInfoQuery {}
|
impl IqGetPayload for DiscoInfoQuery {}
|
||||||
|
|
||||||
/// Structure representing a `<feature xmlns='http://jabber.org/protocol/disco#info'/>` element.
|
|
||||||
#[derive(FromXml, AsXml, Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
#[xml(namespace = ns::DISCO_INFO, name = "feature")]
|
|
||||||
pub struct Feature {
|
|
||||||
/// Namespace of the feature we want to represent.
|
|
||||||
#[xml(attribute)]
|
|
||||||
pub var: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Feature {
|
|
||||||
/// Create a new `<feature/>` with the according `@var`.
|
|
||||||
pub fn new<S: Into<String>>(var: S) -> Feature {
|
|
||||||
Feature { var: var.into() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure representing an `<identity xmlns='http://jabber.org/protocol/disco#info'/>` element.
|
/// Structure representing an `<identity xmlns='http://jabber.org/protocol/disco#info'/>` element.
|
||||||
#[derive(FromXml, AsXml, Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(FromXml, AsXml, Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
#[xml(namespace = ns::DISCO_INFO, name = "identity")]
|
#[xml(namespace = ns::DISCO_INFO, name = "identity")]
|
||||||
|
|
@ -113,8 +97,8 @@ pub struct DiscoInfoResult {
|
||||||
pub identities: Vec<Identity>,
|
pub identities: Vec<Identity>,
|
||||||
|
|
||||||
/// List of features supported by this entity.
|
/// List of features supported by this entity.
|
||||||
#[xml(child(n = ..))]
|
#[xml(extract(n = .., name = "feature", fields(attribute(name = "var", type_ = String))))]
|
||||||
pub features: Vec<Feature>,
|
pub features: Vec<String>,
|
||||||
|
|
||||||
/// List of extensions reported by this entity.
|
/// List of extensions reported by this entity.
|
||||||
#[xml(child(n = ..))]
|
#[xml(child(n = ..))]
|
||||||
|
|
@ -192,7 +176,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Identity, 48);
|
assert_size!(Identity, 48);
|
||||||
assert_size!(Feature, 12);
|
|
||||||
assert_size!(DiscoInfoQuery, 12);
|
assert_size!(DiscoInfoQuery, 12);
|
||||||
assert_size!(DiscoInfoResult, 48);
|
assert_size!(DiscoInfoResult, 48);
|
||||||
|
|
||||||
|
|
@ -205,7 +188,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Identity, 96);
|
assert_size!(Identity, 96);
|
||||||
assert_size!(Feature, 24);
|
|
||||||
assert_size!(DiscoInfoQuery, 24);
|
assert_size!(DiscoInfoQuery, 24);
|
||||||
assert_size!(DiscoInfoResult, 96);
|
assert_size!(DiscoInfoResult, 96);
|
||||||
|
|
||||||
|
|
@ -325,9 +307,11 @@ mod tests {
|
||||||
FromElementError::Invalid(Error::Other(string)) => string,
|
FromElementError::Invalid(Error::Other(string)) => string,
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
};
|
};
|
||||||
|
// TODO: Make xso generate a better error message, with s/unnamed field 0/'var'/ for
|
||||||
|
// instance.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
message,
|
message,
|
||||||
"Required attribute field 'var' on Feature element missing."
|
"Required attribute unnamed field 0 on extraction for field 'features' in DiscoInfoResult element missing."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
use xso::{AsXml, FromXml};
|
use xso::{AsXml, FromXml};
|
||||||
|
|
||||||
use crate::data_forms::DataForm;
|
use crate::data_forms::DataForm;
|
||||||
use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity};
|
use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Identity};
|
||||||
use crate::hashes::{Algo, Hash};
|
use crate::hashes::{Algo, Hash};
|
||||||
use crate::ns;
|
use crate::ns;
|
||||||
use crate::presence::PresencePayload;
|
use crate::presence::PresencePayload;
|
||||||
|
|
@ -64,8 +64,8 @@ fn compute_items<'x, T: 'x, I: IntoIterator<Item = &'x T>, F: Fn(&'x T) -> Vec<u
|
||||||
string
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_features(features: &[Feature]) -> Vec<u8> {
|
fn compute_features(features: &[String]) -> Vec<u8> {
|
||||||
compute_items(features, 0x1c, |feature| compute_item(&feature.var))
|
compute_items(features, 0x1c, |feature| compute_item(&feature))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_identities(identities: &[Identity]) -> Vec<u8> {
|
fn compute_identities(identities: &[Identity]) -> Vec<u8> {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ use tokio_xmpp::{Client, Stanza};
|
||||||
use xmpp_parsers::{
|
use xmpp_parsers::{
|
||||||
avatar::{Data as AvatarData, Metadata as AvatarMetadata},
|
avatar::{Data as AvatarData, Metadata as AvatarMetadata},
|
||||||
caps::{compute_disco, hash_caps, Caps},
|
caps::{compute_disco, hash_caps, Caps},
|
||||||
disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity},
|
disco::{DiscoInfoQuery, DiscoInfoResult, Identity},
|
||||||
hashes::Algo,
|
hashes::Algo,
|
||||||
iq::Iq,
|
iq::Iq,
|
||||||
jid::{BareJid, Jid},
|
jid::{BareJid, Jid},
|
||||||
|
|
@ -185,8 +185,8 @@ 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 = vec![
|
||||||
Feature::new(ns::DISCO_INFO),
|
String::from(ns::DISCO_INFO),
|
||||||
Feature::new(format!("{}+notify", ns::AVATAR_METADATA)),
|
format!("{}+notify", ns::AVATAR_METADATA),
|
||||||
];
|
];
|
||||||
DiscoInfoResult {
|
DiscoInfoResult {
|
||||||
node: None,
|
node: None,
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
Agent, ClientFeature, ClientType, Config, RoomNick,
|
Agent, ClientFeature, ClientType, Config, RoomNick,
|
||||||
jid::{BareJid, Jid, ResourceRef},
|
jid::{BareJid, Jid, ResourceRef},
|
||||||
parsers::{
|
parsers::{
|
||||||
disco::{DiscoInfoResult, Feature, Identity},
|
disco::{DiscoInfoResult, Identity},
|
||||||
ns,
|
ns,
|
||||||
},
|
},
|
||||||
tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts},
|
tokio_xmpp::{Client as TokioXmppClient, connect::ServerConnector, xmlstream::Timeouts},
|
||||||
|
|
@ -107,15 +107,15 @@ impl<C: ServerConnector> ClientBuilder<'_, C> {
|
||||||
"en",
|
"en",
|
||||||
self.config.disco.1.to_string(),
|
self.config.disco.1.to_string(),
|
||||||
)];
|
)];
|
||||||
let mut features = vec![Feature::new(ns::DISCO_INFO)];
|
let mut features = vec![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(Feature::new(format!("{}+notify", ns::AVATAR_METADATA)));
|
features.push(format!("{}+notify", ns::AVATAR_METADATA));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.features.contains(&ClientFeature::JoinRooms) {
|
if self.features.contains(&ClientFeature::JoinRooms) {
|
||||||
features.push(Feature::new(format!("{}+notify", ns::BOOKMARKS2)));
|
features.push(format!("{}+notify", ns::BOOKMARKS2));
|
||||||
}
|
}
|
||||||
DiscoInfoResult {
|
DiscoInfoResult {
|
||||||
node: None,
|
node: None,
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,9 @@ pub async fn handle_disco_info_result(agent: &mut Agent, disco: DiscoInfoResult,
|
||||||
// Trigger bookmarks query
|
// Trigger bookmarks query
|
||||||
// TODO: only send this when the JoinRooms feature is enabled.
|
// TODO: only send this when the JoinRooms feature is enabled.
|
||||||
agent.awaiting_disco_bookmarks_type = false;
|
agent.awaiting_disco_bookmarks_type = false;
|
||||||
let mut perform_bookmarks2 = false;
|
let perform_bookmarks2 = disco
|
||||||
for feature in disco.features {
|
.features
|
||||||
if feature.var == "urn:xmpp:bookmarks:1#compat" {
|
.contains(&String::from("urn:xmpp:bookmarks:1#compat"));
|
||||||
perform_bookmarks2 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if perform_bookmarks2 {
|
if perform_bookmarks2 {
|
||||||
// XEP-0402 bookmarks (modern)
|
// XEP-0402 bookmarks (modern)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue