forked from lavina/lavina
1
0
Fork 0
lavina/crates/proto-xmpp/src/disco.rs

395 lines
12 KiB
Rust
Raw Normal View History

2023-03-28 22:34:12 +00:00
use quick_xml::events::attributes::Attribute;
use quick_xml::events::{BytesEnd, BytesStart, Event};
use quick_xml::name::{QName, ResolveResult};
2023-03-27 21:45:44 +00:00
use crate::xml::*;
2024-03-20 18:59:15 +00:00
use anyhow::{anyhow as ffail, Result};
2023-03-27 21:45:44 +00:00
use super::bind::Jid;
pub const XMLNS_INFO: &'static str = "http://jabber.org/protocol/disco#info";
2023-03-30 12:31:20 +00:00
pub const XMLNS_ITEM: &'static str = "http://jabber.org/protocol/disco#items";
2023-03-27 21:45:44 +00:00
2023-03-27 21:52:31 +00:00
#[derive(PartialEq, Eq, Debug)]
2023-03-27 21:45:44 +00:00
pub struct InfoQuery {
pub node: Option<String>,
pub identity: Vec<Identity>,
pub feature: Vec<Feature>,
}
impl FromXml for InfoQuery {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let mut node = None;
let mut identity = vec![];
let mut feature = vec![];
let (bytes, end) = match event {
Event::Start(bytes) => (bytes, false),
Event::Empty(bytes) => (bytes, true),
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
for attr in bytes.attributes() {
let attr = attr?;
match attr.key.0 {
b"node" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
node = Some(s.to_owned())
}
_ => {}
}
}
if end {
2023-03-27 21:52:31 +00:00
return Ok(InfoQuery {
node,
identity,
feature,
});
2023-03-27 21:45:44 +00:00
}
loop {
let (namespace, event) = yield;
let bytes = match event {
Event::Start(bytes) => bytes,
Event::Empty(bytes) => bytes,
Event::End(_) => break,
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
if bytes.name().0 == Identity::NAME.as_bytes() {
let res = delegate_parsing!(Identity, namespace, event)?;
identity.push(res);
} else if bytes.name().0 == Feature::NAME.as_bytes() {
let res = delegate_parsing!(Feature, namespace, event)?;
feature.push(res);
} else {
return Err(ffail!("Unexpected XML event: {event:?}"));
}
}
2023-03-27 21:52:31 +00:00
return Ok(InfoQuery {
node,
identity,
feature,
});
2023-03-27 21:45:44 +00:00
}
}
}
impl FromXmlTag for InfoQuery {
const NAME: &'static str = "query";
const NS: &'static str = XMLNS_INFO;
}
2023-03-28 22:34:12 +00:00
impl ToXml for InfoQuery {
fn serialize(&self, events: &mut Vec<Event<'static>>) {
let mut bytes = BytesStart::new(format!(r#"query xmlns="{}""#, XMLNS_INFO));
if let Some(node) = &self.node {
bytes.push_attribute(Attribute {
key: QName(b"node"),
value: node.as_bytes().into(),
});
}
let empty = self.feature.is_empty() && self.identity.is_empty();
if empty {
events.push(Event::Empty(bytes));
} else {
events.push(Event::Start(bytes));
}
for i in &self.identity {
let mut bytes = BytesStart::new("identity");
bytes.push_attribute(Attribute {
key: QName(b"category"),
value: i.category.as_bytes().into(),
});
if let Some(name) = &i.name {
bytes.push_attribute(Attribute {
key: QName(b"name"),
value: name.as_bytes().into(),
});
}
bytes.push_attribute(Attribute {
key: QName(b"type"),
value: i.r#type.as_bytes().into(),
});
events.push(Event::Empty(bytes));
}
for f in &self.feature {
let mut bytes = BytesStart::new("feature");
bytes.push_attribute(Attribute {
key: QName(b"var"),
value: f.var.as_bytes().into(),
});
events.push(Event::Empty(bytes));
}
if !empty {
events.push(Event::End(BytesEnd::new("query")));
}
}
}
2023-03-27 21:52:31 +00:00
#[derive(PartialEq, Eq, Debug)]
2023-03-27 21:45:44 +00:00
pub struct Identity {
2023-04-05 20:37:33 +00:00
pub category: String,
pub name: Option<String>,
pub r#type: String,
2023-03-27 21:45:44 +00:00
}
impl FromXml for Identity {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let mut category = None;
let mut name = None;
let mut r#type = None;
let (bytes, end) = match event {
Event::Start(bytes) => (bytes, false),
Event::Empty(bytes) => (bytes, true),
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
for attr in bytes.attributes() {
let attr = attr?;
match attr.key.0 {
b"category" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
category = Some(s.to_owned())
}
b"name" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
name = Some(s.to_owned())
}
b"type" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
r#type = Some(s.to_owned())
}
_ => {}
}
}
let Some(category) = category else {
return Err(ffail!("No jid provided"));
};
let Some(r#type) = r#type else {
return Err(ffail!("No type provided"));
};
2024-03-20 18:59:15 +00:00
let item = Identity { category, name, r#type };
2023-03-27 21:45:44 +00:00
if end {
return Ok(item);
}
let (namespace, event) = yield;
let Event::End(bytes) = event else {
return Err(ffail!("Unexpected XML event: {event:?}"));
};
Ok(item)
}
}
}
impl FromXmlTag for Identity {
const NAME: &'static str = "identity";
const NS: &'static str = XMLNS_INFO;
}
2023-03-27 21:52:31 +00:00
#[derive(PartialEq, Eq, Debug)]
2023-03-27 21:45:44 +00:00
pub struct Feature {
pub var: String,
}
2023-03-30 12:31:20 +00:00
impl Feature {
pub fn new(s: &str) -> Feature {
Feature { var: s.to_string() }
}
}
2023-03-27 21:45:44 +00:00
impl FromXml for Feature {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let mut var = None;
let (bytes, end) = match event {
Event::Start(bytes) => (bytes, false),
Event::Empty(bytes) => (bytes, true),
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
for attr in bytes.attributes() {
let attr = attr?;
match attr.key.0 {
b"var" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
var = Some(s.to_owned())
}
_ => {}
}
}
let Some(var) = var else {
return Err(ffail!("No jid provided"));
};
let item = Feature { var };
if end {
return Ok(item);
}
let (namespace, event) = yield;
let Event::End(bytes) = event else {
return Err(ffail!("Unexpected XML event: {event:?}"));
};
Ok(item)
}
}
}
impl FromXmlTag for Feature {
const NAME: &'static str = "feature";
const NS: &'static str = XMLNS_INFO;
}
2023-03-27 21:52:31 +00:00
#[derive(PartialEq, Eq, Debug)]
2023-03-27 21:45:44 +00:00
pub struct ItemQuery {
pub item: Vec<Item>,
}
impl FromXml for ItemQuery {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let mut item = vec![];
let (bytes, end) = match event {
Event::Start(bytes) => (bytes, false),
Event::Empty(bytes) => (bytes, true),
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
if end {
2023-03-27 21:52:31 +00:00
return Ok(ItemQuery { item });
2023-03-27 21:45:44 +00:00
}
loop {
let (namespace, event) = yield;
let bytes = match event {
Event::Start(bytes) => bytes,
Event::Empty(bytes) => bytes,
Event::End(_) => break,
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
if bytes.name().0 == Item::NAME.as_bytes() {
let res = delegate_parsing!(Item, namespace, event)?;
item.push(res);
} else {
return Err(ffail!("Unexpected XML event: {event:?}"));
}
}
Ok(ItemQuery { item })
}
}
}
impl FromXmlTag for ItemQuery {
const NAME: &'static str = "query";
const NS: &'static str = XMLNS_ITEM;
}
2023-03-28 22:34:12 +00:00
impl ToXml for ItemQuery {
fn serialize(&self, events: &mut Vec<Event<'static>>) {
let mut bytes = BytesStart::new(format!(r#"query xmlns="{}""#, XMLNS_ITEM));
let empty = self.item.is_empty();
if empty {
events.push(Event::Empty(bytes));
} else {
events.push(Event::Start(bytes));
}
for f in &self.item {
let mut bytes = BytesStart::new("item");
bytes.push_attribute(Attribute {
key: QName(b"jid"),
value: f.jid.to_string().into_bytes().into(),
});
if let Some(name) = &f.name {
bytes.push_attribute(Attribute {
key: QName(b"name"),
value: name.as_bytes().into(),
});
}
if let Some(node) = &f.node {
bytes.push_attribute(Attribute {
key: QName(b"node"),
value: node.as_bytes().into(),
});
}
events.push(Event::Empty(bytes));
}
if !empty {
events.push(Event::End(BytesEnd::new("query")));
}
}
}
2023-03-27 21:52:31 +00:00
#[derive(PartialEq, Eq, Debug)]
2023-03-27 21:45:44 +00:00
pub struct Item {
pub jid: super::bind::Jid,
pub name: Option<String>,
pub node: Option<String>,
}
impl FromXml for Item {
type P = impl Parser<Output = Result<Self>>;
fn parse() -> Self::P {
|(namespace, event): (ResolveResult<'static>, &'static Event<'static>)| -> Result<Self> {
let mut jid = None;
let mut name = None;
let mut node = None;
let (bytes, end) = match event {
Event::Start(bytes) => (bytes, false),
Event::Empty(bytes) => (bytes, true),
_ => return Err(ffail!("Unexpected XML event: {event:?}")),
};
for attr in bytes.attributes() {
let attr = attr?;
match attr.key.0 {
b"name" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
name = Some(s.to_owned())
}
b"node" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
node = Some(s.to_owned())
}
b"jid" => {
let s = std::str::from_utf8(&attr.value)?;
2023-03-27 21:45:44 +00:00
let s = Jid::from_string(s)?;
jid = Some(s)
}
_ => {}
}
}
let Some(jid) = jid else {
return Err(ffail!("No jid provided"));
};
let item = Item { jid, name, node };
if end {
return Ok(item);
}
let (namespace, event) = yield;
let Event::End(bytes) = event else {
return Err(ffail!("Unexpected XML event: {event:?}"));
};
Ok(item)
}
}
}
impl FromXmlTag for Item {
const NAME: &'static str = "item";
const NS: &'static str = XMLNS_ITEM;
2023-03-27 21:52:31 +00:00
}