forked from lavina/lavina
289 lines
9.1 KiB
Rust
289 lines
9.1 KiB
Rust
use quick_xml::events::Event;
|
|
use quick_xml::name::ResolveResult;
|
|
|
|
use crate::prelude::*;
|
|
use crate::util::xml::*;
|
|
|
|
use super::bind::Jid;
|
|
|
|
pub const XMLNS_INFO: &'static str = "http://jabber.org/protocol/disco#info";
|
|
pub const XMLNS_ITEM: &'static str = "http://jabber.org/protocol/disco#item";
|
|
|
|
|
|
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(bytes)?;
|
|
node = Some(s.to_owned())
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
if end {
|
|
return Ok(InfoQuery { node, identity, feature })
|
|
}
|
|
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:?}"));
|
|
}
|
|
}
|
|
return Ok(InfoQuery { node, identity, feature })
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromXmlTag for InfoQuery {
|
|
const NAME: &'static str = "query";
|
|
|
|
const NS: &'static str = XMLNS_INFO;
|
|
}
|
|
|
|
pub struct Identity {
|
|
category: String,
|
|
name: Option<String>,
|
|
r#type: String,
|
|
}
|
|
|
|
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(bytes)?;
|
|
category = Some(s.to_owned())
|
|
}
|
|
b"name" => {
|
|
let s = std::str::from_utf8(bytes)?;
|
|
name = Some(s.to_owned())
|
|
}
|
|
b"type" => {
|
|
let s = std::str::from_utf8(bytes)?;
|
|
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"));
|
|
};
|
|
let item = Identity { category, name, r#type };
|
|
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;
|
|
}
|
|
|
|
pub struct Feature {
|
|
pub var: String,
|
|
}
|
|
|
|
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(bytes)?;
|
|
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;
|
|
}
|
|
|
|
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 {
|
|
return Ok(ItemQuery { item })
|
|
}
|
|
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;
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
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(bytes)?;
|
|
name = Some(s.to_owned())
|
|
}
|
|
b"node" => {
|
|
let s = std::str::from_utf8(bytes)?;
|
|
node = Some(s.to_owned())
|
|
}
|
|
b"jid" => {
|
|
let s = std::str::from_utf8(bytes)?;
|
|
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;
|
|
} |