Implement macro for elements containing text
This commit is contained in:
parent
9c9ffe70a7
commit
77e150c63d
2 changed files with 57 additions and 30 deletions
45
src/ibb.rs
45
src/ibb.rs
|
|
@ -25,41 +25,26 @@ generate_element_with_only_attributes!(Open, "open", ns::IBB, [
|
||||||
stanza: Stanza = "stanza" => default,
|
stanza: Stanza = "stanza" => default,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
/// Codec wrapping base64 encode/decode
|
||||||
pub struct Data {
|
struct Base64;
|
||||||
pub seq: u16,
|
|
||||||
pub sid: String,
|
impl Base64 {
|
||||||
pub data: Vec<u8>,
|
fn decode(s: &str) -> Result<Vec<u8>, Error> {
|
||||||
|
Ok(base64::decode(s)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Element> for Data {
|
fn encode(b: &Vec<u8>) -> String {
|
||||||
type Err = Error;
|
base64::encode(b)
|
||||||
|
|
||||||
fn try_from(elem: Element) -> Result<Data, Error> {
|
|
||||||
if !elem.is("data", ns::IBB) {
|
|
||||||
return Err(Error::ParseError("This is not a data element."));
|
|
||||||
}
|
|
||||||
for _ in elem.children() {
|
|
||||||
return Err(Error::ParseError("Unknown child in data element."));
|
|
||||||
}
|
|
||||||
Ok(Data {
|
|
||||||
seq: get_attr!(elem, "seq", required),
|
|
||||||
sid: get_attr!(elem, "sid", required),
|
|
||||||
data: base64::decode(&elem.text())?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Data> for Element {
|
generate_element_with_text!(Data, "data", ns::IBB,
|
||||||
fn from(data: Data) -> Element {
|
[
|
||||||
Element::builder("data")
|
seq: u16 = "seq" => required,
|
||||||
.ns(ns::IBB)
|
sid: String = "sid" => required
|
||||||
.attr("seq", data.seq)
|
],
|
||||||
.attr("sid", data.sid)
|
data: Base64<Vec<u8>>
|
||||||
.append(base64::encode(&data.data))
|
);
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_element_with_only_attributes!(Close, "close", ns::IBB, [
|
generate_element_with_only_attributes!(Close, "close", ns::IBB, [
|
||||||
sid: String = "sid" => required,
|
sid: String = "sid" => required,
|
||||||
|
|
|
||||||
|
|
@ -251,3 +251,45 @@ macro_rules! generate_elem_id {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! generate_element_with_text {
|
||||||
|
($(#[$meta:meta])* $elem:ident, $name:tt, $ns:expr, [$($(#[$attr_meta:meta])* $attr:ident: $attr_type:ty = $attr_name:tt => $attr_action:tt),+], $text_ident:ident: $codec:ident < $text_type:ty >) => (
|
||||||
|
$(#[$meta])*
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct $elem {
|
||||||
|
$(
|
||||||
|
$(#[$attr_meta])*
|
||||||
|
pub $attr: $attr_type
|
||||||
|
),*,
|
||||||
|
pub $text_ident: $text_type,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Element> for $elem {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn try_from(elem: Element) -> Result<$elem, Error> {
|
||||||
|
check_self!(elem, $name, $ns);
|
||||||
|
check_no_children!(elem, $name);
|
||||||
|
check_no_unknown_attributes!(elem, $name, [$($attr_name),*]);
|
||||||
|
Ok($elem {
|
||||||
|
$(
|
||||||
|
$attr: get_attr!(elem, $attr_name, $attr_action)
|
||||||
|
),*,
|
||||||
|
$text_ident: $codec::decode(&elem.text())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$elem> for Element {
|
||||||
|
fn from(elem: $elem) -> Element {
|
||||||
|
Element::builder($name)
|
||||||
|
.ns($ns)
|
||||||
|
$(
|
||||||
|
.attr($attr_name, elem.$attr)
|
||||||
|
)*
|
||||||
|
.append($codec::encode(&elem.$text_ident))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue