mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-06-02 14:29:20 +02:00
cargo fmt
This commit is contained in:
parent
14653c1396
commit
d976200302
|
@ -96,4 +96,4 @@ pub use error::{Error, Result};
|
||||||
pub use namespaces::NSChoice;
|
pub use namespaces::NSChoice;
|
||||||
pub use node::Node;
|
pub use node::Node;
|
||||||
pub use token::Token;
|
pub use token::Token;
|
||||||
pub use tokenizer::{Tokenizer, TokenizerError, tokenize};
|
pub use tokenizer::{tokenize, Tokenizer, TokenizerError};
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
//! Parsed XML token
|
//! Parsed XML token
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::streaming::{tag, take_while1},
|
bytes::streaming::{tag, take_while1},
|
||||||
character::{is_space, streaming::{char, digit1, one_of, space0, space1}},
|
character::{
|
||||||
|
is_space,
|
||||||
|
streaming::{char, digit1, one_of, space0, space1},
|
||||||
|
},
|
||||||
combinator::{not, peek, value},
|
combinator::{not, peek, value},
|
||||||
multi::many0,
|
multi::many0,
|
||||||
number::streaming::hex_u32,
|
number::streaming::hex_u32,
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
/// Attribute name with prefix
|
/// Attribute name with prefix
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
@ -23,16 +26,14 @@ pub struct LocalName {
|
||||||
impl From<&str> for LocalName {
|
impl From<&str> for LocalName {
|
||||||
fn from(s: &str) -> Self {
|
fn from(s: &str) -> Self {
|
||||||
match s.split_once(':') {
|
match s.split_once(':') {
|
||||||
Some((prefix, name)) =>
|
Some((prefix, name)) => LocalName {
|
||||||
LocalName {
|
prefix: Some(prefix.to_owned()),
|
||||||
prefix: Some(prefix.to_owned()),
|
name: name.to_owned(),
|
||||||
name: name.to_owned(),
|
},
|
||||||
},
|
None => LocalName {
|
||||||
None =>
|
prefix: None,
|
||||||
LocalName {
|
name: s.to_owned(),
|
||||||
prefix: None,
|
},
|
||||||
name: s.to_owned(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,97 +76,109 @@ pub enum Token {
|
||||||
impl Token {
|
impl Token {
|
||||||
/// Parse one token
|
/// Parse one token
|
||||||
pub fn parse(s: &[u8]) -> IResult<&[u8], Token> {
|
pub fn parse(s: &[u8]) -> IResult<&[u8], Token> {
|
||||||
alt((
|
alt((Self::parse_tag, |s| {
|
||||||
Self::parse_tag,
|
let (s, _) = not(peek(char('<')))(s)?;
|
||||||
|s| {
|
let (s, text) = Self::parse_text('<', s)?;
|
||||||
let (s, _) = not(peek(char('<')))(s)?;
|
Ok((s, Token::Text(text.into_owned())))
|
||||||
let (s, text) = Self::parse_text('<', s)?;
|
}))(s)
|
||||||
Ok((s, Token::Text(text.into_owned())))
|
|
||||||
},
|
|
||||||
))(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tag(s: &[u8]) -> IResult<&[u8], Token> {
|
fn parse_tag(s: &[u8]) -> IResult<&[u8], Token> {
|
||||||
let (s, _) = tag("<")(s)?;
|
let (s, _) = tag("<")(s)?;
|
||||||
alt((|s| -> IResult<&[u8], Token> {
|
alt((
|
||||||
// CDATA
|
|s| -> IResult<&[u8], Token> {
|
||||||
let (s, _) = tag("![CDATA[")(s)?;
|
// CDATA
|
||||||
let mut end = None;
|
let (s, _) = tag("![CDATA[")(s)?;
|
||||||
for i in 0..s.len() - 2 {
|
let mut end = None;
|
||||||
if &s[i..i + 3] == b"]]>" {
|
for i in 0..s.len() - 2 {
|
||||||
end = Some(i);
|
if &s[i..i + 3] == b"]]>" {
|
||||||
break
|
end = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if let Some(end) = end {
|
||||||
if let Some(end) = end {
|
let text = Self::str_from_utf8(&s[..end])?;
|
||||||
let text = Self::str_from_utf8(&s[..end])?;
|
Ok((&s[end + 3..], Token::Text(text.to_string())))
|
||||||
Ok((&s[end + 3..], Token::Text(text.to_string())))
|
} else {
|
||||||
} else {
|
Err(nom::Err::Incomplete(nom::Needed::Unknown))
|
||||||
Err(nom::Err::Incomplete(nom::Needed::Unknown))
|
}
|
||||||
}
|
},
|
||||||
}, |s| {
|
|s| {
|
||||||
// XmlDecl
|
// XmlDecl
|
||||||
let (s, _) = tag("?xml")(s)?;
|
let (s, _) = tag("?xml")(s)?;
|
||||||
let (s, _) = space1(s)?;
|
let (s, _) = space1(s)?;
|
||||||
|
|
||||||
|
let (s, attrs) = many0(|s| {
|
||||||
|
let (s, (name, value)) = Self::parse_attr(s)?;
|
||||||
|
let (s, _) = space0(s)?;
|
||||||
|
Ok((s, (name, value)))
|
||||||
|
})(s)?;
|
||||||
|
|
||||||
let (s, attrs) = many0(|s| {
|
|
||||||
let (s, (name, value)) = Self::parse_attr(s)?;
|
|
||||||
let (s, _) = space0(s)?;
|
let (s, _) = space0(s)?;
|
||||||
Ok((s, (name, value)))
|
let (s, _) = tag("?>")(s)?;
|
||||||
})(s)?;
|
Ok((
|
||||||
|
s,
|
||||||
let (s, _) = space0(s)?;
|
Token::XmlDecl {
|
||||||
let (s, _) = tag("?>")(s)?;
|
attrs: attrs
|
||||||
Ok((s, Token::XmlDecl {
|
.into_iter()
|
||||||
attrs: attrs.into_iter()
|
.map(|(name, value)| Attribute {
|
||||||
.map(|(name, value)| Attribute {
|
name: name.into(),
|
||||||
name: name.into(),
|
value: value.into_owned(),
|
||||||
value: value.into_owned(),
|
})
|
||||||
})
|
.collect(),
|
||||||
.collect(),
|
},
|
||||||
}))
|
))
|
||||||
}, |s| {
|
},
|
||||||
// EndTag
|
|s| {
|
||||||
let (s, _) = tag("/")(s)?;
|
// EndTag
|
||||||
let (s, _) = space0(s)?;
|
|
||||||
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>'))(s)?;
|
|
||||||
let (s, _) = space0(s)?;
|
|
||||||
let (s, _) = tag(">")(s)?;
|
|
||||||
let name = Self::str_from_utf8(name)?;
|
|
||||||
Ok((s, Token::EndTag { name: name.into() }))
|
|
||||||
}, |s| {
|
|
||||||
// StartTag
|
|
||||||
let (s, _) = space0(s)?;
|
|
||||||
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>' || b == b'/'))(s)?;
|
|
||||||
let (s, _) = space0(s)?;
|
|
||||||
let (s, attrs) = many0(|s| {
|
|
||||||
let (s, (name, value)) = Self::parse_attr(s)?;
|
|
||||||
let (s, _) = space0(s)?;
|
|
||||||
Ok((s, (name, value)))
|
|
||||||
})(s)?;
|
|
||||||
|
|
||||||
let (s, self_closing) = alt((|s| {
|
|
||||||
let (s, _) = tag("/")(s)?;
|
let (s, _) = tag("/")(s)?;
|
||||||
let (s, _) = space0(s)?;
|
let (s, _) = space0(s)?;
|
||||||
|
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>'))(s)?;
|
||||||
|
let (s, _) = space0(s)?;
|
||||||
let (s, _) = tag(">")(s)?;
|
let (s, _) = tag(">")(s)?;
|
||||||
Ok((s, true))
|
let name = Self::str_from_utf8(name)?;
|
||||||
}, |s| {
|
Ok((s, Token::EndTag { name: name.into() }))
|
||||||
let (s, _) = tag(">")(s)?;
|
},
|
||||||
Ok((s, false))
|
|s| {
|
||||||
}))(s)?;
|
// StartTag
|
||||||
|
let (s, _) = space0(s)?;
|
||||||
|
let (s, name) = take_while1(|b| !(is_space(b) || b == b'>' || b == b'/'))(s)?;
|
||||||
|
let (s, _) = space0(s)?;
|
||||||
|
let (s, attrs) = many0(|s| {
|
||||||
|
let (s, (name, value)) = Self::parse_attr(s)?;
|
||||||
|
let (s, _) = space0(s)?;
|
||||||
|
Ok((s, (name, value)))
|
||||||
|
})(s)?;
|
||||||
|
|
||||||
Ok((s, Token::StartTag {
|
let (s, self_closing) = alt((
|
||||||
name: Self::str_from_utf8(name)?
|
|s| {
|
||||||
.into(),
|
let (s, _) = tag("/")(s)?;
|
||||||
attrs: attrs.into_iter()
|
let (s, _) = space0(s)?;
|
||||||
.map(|(name, value)| Attribute {
|
let (s, _) = tag(">")(s)?;
|
||||||
name: name.into(),
|
Ok((s, true))
|
||||||
value: value.into_owned(),
|
},
|
||||||
})
|
|s| {
|
||||||
.collect(),
|
let (s, _) = tag(">")(s)?;
|
||||||
self_closing,
|
Ok((s, false))
|
||||||
}))
|
},
|
||||||
}))(s)
|
))(s)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
s,
|
||||||
|
Token::StartTag {
|
||||||
|
name: Self::str_from_utf8(name)?.into(),
|
||||||
|
attrs: attrs
|
||||||
|
.into_iter()
|
||||||
|
.map(|(name, value)| Attribute {
|
||||||
|
name: name.into(),
|
||||||
|
value: value.into_owned(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
self_closing,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
},
|
||||||
|
))(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attr(s: &[u8]) -> IResult<&[u8], (&str, Cow<str>)> {
|
fn parse_attr(s: &[u8]) -> IResult<&[u8], (&str, Cow<str>)> {
|
||||||
|
@ -182,54 +195,51 @@ impl Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_text(until: char, s: &[u8]) -> IResult<&[u8], Cow<str>> {
|
fn parse_text(until: char, s: &[u8]) -> IResult<&[u8], Cow<str>> {
|
||||||
let (s, results) = many0(
|
let (s, results) = many0(alt((
|
||||||
alt(
|
|s| {
|
||||||
(|s| {
|
let (s, _) = tag("&#")(s)?;
|
||||||
let (s, _) = tag("&#")(s)?;
|
let (s, num) = digit1(s)?;
|
||||||
let (s, num) = digit1(s)?;
|
let (s, _) = char(';')(s)?;
|
||||||
let (s, _) = char(';')(s)?;
|
let num: u32 = Self::str_from_utf8(num)?.parse().map_err(|_| {
|
||||||
let num: u32 = Self::str_from_utf8(num)?
|
nom::Err::Failure(nom::error::Error::new(s, nom::error::ErrorKind::Fail))
|
||||||
.parse()
|
})?;
|
||||||
.map_err(|_| nom::Err::Failure(nom::error::Error::new(s, nom::error::ErrorKind::Fail)))?;
|
if let Some(c) = std::char::from_u32(num) {
|
||||||
if let Some(c) = std::char::from_u32(num) {
|
|
||||||
Ok((s, Cow::from(format!("{}", c))))
|
|
||||||
} else {
|
|
||||||
Ok((s, Cow::from(format!(""))))
|
|
||||||
}
|
|
||||||
}, |s| {
|
|
||||||
let (s, _) = tag("&#x")(s)?;
|
|
||||||
let (s, num) = hex_u32(s)?;
|
|
||||||
let (s, _) = char(';')(s)?;
|
|
||||||
if let Some(c) = std::char::from_u32(num) {
|
|
||||||
Ok((s, Cow::from(format!("{}", c))))
|
|
||||||
} else {
|
|
||||||
Ok((s, Cow::from(format!(""))))
|
|
||||||
}
|
|
||||||
}, |s| {
|
|
||||||
let (s, _) = char('&')(s)?;
|
|
||||||
let (s, c) = alt((
|
|
||||||
value('&', tag("amp")),
|
|
||||||
value('<', tag("lt")),
|
|
||||||
value('>', tag("gt")),
|
|
||||||
value('"', tag("quot")),
|
|
||||||
value('\'', tag("apos")),
|
|
||||||
))(s)?;
|
|
||||||
let (s, _) = char(';')(s)?;
|
|
||||||
Ok((s, Cow::from(format!("{}", c))))
|
Ok((s, Cow::from(format!("{}", c))))
|
||||||
}, |s| {
|
} else {
|
||||||
let (s, _) = not(peek(char(until)))(s)?;
|
Ok((s, Cow::from(format!(""))))
|
||||||
let (s, text) = take_while1(|b|
|
}
|
||||||
b != until as u8 &&
|
},
|
||||||
b != b'&' &&
|
|s| {
|
||||||
b != b'<' &&
|
let (s, _) = tag("&#x")(s)?;
|
||||||
b != b'>'
|
let (s, num) = hex_u32(s)?;
|
||||||
)(s)?;
|
let (s, _) = char(';')(s)?;
|
||||||
let text = Self::str_from_utf8(text)?;
|
if let Some(c) = std::char::from_u32(num) {
|
||||||
let text = Self::normalize_newlines(text);
|
Ok((s, Cow::from(format!("{}", c))))
|
||||||
Ok((s, text))
|
} else {
|
||||||
})
|
Ok((s, Cow::from(format!(""))))
|
||||||
)
|
}
|
||||||
)(s)?;
|
},
|
||||||
|
|s| {
|
||||||
|
let (s, _) = char('&')(s)?;
|
||||||
|
let (s, c) = alt((
|
||||||
|
value('&', tag("amp")),
|
||||||
|
value('<', tag("lt")),
|
||||||
|
value('>', tag("gt")),
|
||||||
|
value('"', tag("quot")),
|
||||||
|
value('\'', tag("apos")),
|
||||||
|
))(s)?;
|
||||||
|
let (s, _) = char(';')(s)?;
|
||||||
|
Ok((s, Cow::from(format!("{}", c))))
|
||||||
|
},
|
||||||
|
|s| {
|
||||||
|
let (s, _) = not(peek(char(until)))(s)?;
|
||||||
|
let (s, text) =
|
||||||
|
take_while1(|b| b != until as u8 && b != b'&' && b != b'<' && b != b'>')(s)?;
|
||||||
|
let text = Self::str_from_utf8(text)?;
|
||||||
|
let text = Self::normalize_newlines(text);
|
||||||
|
Ok((s, text))
|
||||||
|
},
|
||||||
|
)))(s)?;
|
||||||
|
|
||||||
if results.len() == 1 {
|
if results.len() == 1 {
|
||||||
Ok((s, results.into_iter().next().unwrap()))
|
Ok((s, results.into_iter().next().unwrap()))
|
||||||
|
@ -329,11 +339,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tag() {
|
fn test_tag() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "foobar".into(),
|
&b""[..],
|
||||||
attrs: vec![],
|
Token::StartTag {
|
||||||
self_closing: false,
|
name: "foobar".into(),
|
||||||
})),
|
attrs: vec![],
|
||||||
|
self_closing: false,
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<foobar>")
|
Token::parse(b"<foobar>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -341,15 +354,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attrs() {
|
fn test_attrs() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "a".into(),
|
&b""[..],
|
||||||
attrs: vec![
|
Token::StartTag {
|
||||||
attr("a", "2'3"),
|
name: "a".into(),
|
||||||
attr("b", "4\"2"),
|
attrs: vec![attr("a", "2'3"), attr("b", "4\"2"), attr("c", ""),],
|
||||||
attr("c", ""),
|
self_closing: false,
|
||||||
],
|
}
|
||||||
self_closing: false,
|
)),
|
||||||
})),
|
|
||||||
Token::parse(b"<a a=\"2'3\" b = '4\"2' c = ''>")
|
Token::parse(b"<a a=\"2'3\" b = '4\"2' c = ''>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -357,15 +369,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attrs_normalized() {
|
fn test_attrs_normalized() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "a".into(),
|
&b""[..],
|
||||||
attrs: vec![
|
Token::StartTag {
|
||||||
attr("a", "x y"),
|
name: "a".into(),
|
||||||
attr("b", " "),
|
attrs: vec![attr("a", "x y"), attr("b", " "), attr("c", "a b"),],
|
||||||
attr("c", "a b"),
|
self_closing: false,
|
||||||
],
|
}
|
||||||
self_closing: false,
|
)),
|
||||||
})),
|
|
||||||
Token::parse(b"<a a=\"x\ty\" b = '\r\n' c = 'a\r\rb'>")
|
Token::parse(b"<a a=\"x\ty\" b = '\r\n' c = 'a\r\rb'>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -373,13 +384,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attrs_entities() {
|
fn test_attrs_entities() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "a".into(),
|
&b""[..],
|
||||||
attrs: vec![
|
Token::StartTag {
|
||||||
attr("a", "<3"),
|
name: "a".into(),
|
||||||
],
|
attrs: vec![attr("a", "<3"),],
|
||||||
self_closing: false,
|
self_closing: false,
|
||||||
})),
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<a a='<3'>")
|
Token::parse(b"<a a='<3'>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -387,11 +399,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_self_closing_tag() {
|
fn test_self_closing_tag() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "foobar".into(),
|
&b""[..],
|
||||||
attrs: vec![],
|
Token::StartTag {
|
||||||
self_closing: true,
|
name: "foobar".into(),
|
||||||
})),
|
attrs: vec![],
|
||||||
|
self_closing: true,
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<foobar/>")
|
Token::parse(b"<foobar/>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -399,9 +414,12 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_end_tag() {
|
fn test_end_tag() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::EndTag {
|
Ok((
|
||||||
name: "foobar".into(),
|
&b""[..],
|
||||||
})),
|
Token::EndTag {
|
||||||
|
name: "foobar".into(),
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"</foobar>")
|
Token::parse(b"</foobar>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -409,14 +427,17 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_element_prefix() {
|
fn test_element_prefix() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: LocalName {
|
&b""[..],
|
||||||
name: "z".to_owned(),
|
Token::StartTag {
|
||||||
prefix: Some("x".to_owned()),
|
name: LocalName {
|
||||||
},
|
name: "z".to_owned(),
|
||||||
attrs: vec![],
|
prefix: Some("x".to_owned()),
|
||||||
self_closing: true,
|
},
|
||||||
})),
|
attrs: vec![],
|
||||||
|
self_closing: true,
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<x:z/>")
|
Token::parse(b"<x:z/>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -424,17 +445,20 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_attr_prefix() {
|
fn test_attr_prefix() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::StartTag {
|
Ok((
|
||||||
name: "a".into(),
|
&b""[..],
|
||||||
attrs: vec![Attribute {
|
Token::StartTag {
|
||||||
name: LocalName {
|
name: "a".into(),
|
||||||
name: "abc".to_owned(),
|
attrs: vec![Attribute {
|
||||||
prefix: Some("xyz".to_owned()),
|
name: LocalName {
|
||||||
},
|
name: "abc".to_owned(),
|
||||||
value: "".to_owned(),
|
prefix: Some("xyz".to_owned()),
|
||||||
}],
|
},
|
||||||
self_closing: false,
|
value: "".to_owned(),
|
||||||
})),
|
}],
|
||||||
|
self_closing: false,
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<a xyz:abc=''>")
|
Token::parse(b"<a xyz:abc=''>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -442,21 +466,27 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_xml_decl() {
|
fn test_xml_decl() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Ok((&b""[..], Token::XmlDecl {
|
Ok((
|
||||||
attrs: vec![Attribute {
|
&b""[..],
|
||||||
name: LocalName {
|
Token::XmlDecl {
|
||||||
name: "version".to_owned(),
|
attrs: vec![
|
||||||
prefix: None,
|
Attribute {
|
||||||
},
|
name: LocalName {
|
||||||
value: "1.0".to_owned(),
|
name: "version".to_owned(),
|
||||||
}, Attribute {
|
prefix: None,
|
||||||
name: LocalName {
|
},
|
||||||
name: "encoding".to_owned(),
|
value: "1.0".to_owned(),
|
||||||
prefix: None,
|
},
|
||||||
},
|
Attribute {
|
||||||
value: "UTF-8".to_owned(),
|
name: LocalName {
|
||||||
}],
|
name: "encoding".to_owned(),
|
||||||
})),
|
prefix: None,
|
||||||
|
},
|
||||||
|
value: "UTF-8".to_owned(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)),
|
||||||
Token::parse(b"<?xml version='1.0' encoding=\"UTF-8\"?>")
|
Token::parse(b"<?xml version='1.0' encoding=\"UTF-8\"?>")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
//! Streaming tokenizer (SAX parser)
|
//! Streaming tokenizer (SAX parser)
|
||||||
|
|
||||||
use bytes::BytesMut;
|
|
||||||
use super::{Error, Token};
|
use super::{Error, Token};
|
||||||
|
use bytes::BytesMut;
|
||||||
|
|
||||||
/// `Result::Err` type returned from `Tokenizer`
|
/// `Result::Err` type returned from `Tokenizer`
|
||||||
pub type TokenizerError = nom::error::Error<String>;
|
pub type TokenizerError = nom::error::Error<String>;
|
||||||
|
@ -55,26 +55,23 @@ pub fn tokenize(buffer: &mut BytesMut) -> Result<Option<Token>, Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result: Option<(usize, Token)> = { match Token::parse(&buffer) {
|
let result: Option<(usize, Token)> = {
|
||||||
Ok((s, token)) =>
|
match Token::parse(&buffer) {
|
||||||
Some((s.len(), token)),
|
Ok((s, token)) => Some((s.len(), token)),
|
||||||
Result::Err(nom::Err::Incomplete(_)) =>
|
Result::Err(nom::Err::Incomplete(_)) => None,
|
||||||
None,
|
Result::Err(nom::Err::Error(e)) => return Err(with_input_to_owned(e).into()),
|
||||||
Result::Err(nom::Err::Error(e)) =>
|
Result::Err(nom::Err::Failure(e)) => return Err(with_input_to_owned(e).into()),
|
||||||
return Err(with_input_to_owned(e).into()),
|
}
|
||||||
Result::Err(nom::Err::Failure(e)) =>
|
};
|
||||||
return Err(with_input_to_owned(e).into()),
|
|
||||||
} };
|
|
||||||
match result {
|
match result {
|
||||||
Some((s_len, token)) => {
|
Some((s_len, token)) => {
|
||||||
let _ = buffer.split_to(buffer.len() - s_len);
|
let _ = buffer.split_to(buffer.len() - s_len);
|
||||||
Ok(Some(token))
|
Ok(Some(token))
|
||||||
}
|
}
|
||||||
None => Ok(None)
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -101,20 +98,21 @@ mod tests {
|
||||||
|
|
||||||
let buf = b"<foo bar='baz'>quux</foo>";
|
let buf = b"<foo bar='baz'>quux</foo>";
|
||||||
for chunk_size in 1..=buf.len() {
|
for chunk_size in 1..=buf.len() {
|
||||||
assert_eq!(vec![
|
assert_eq!(
|
||||||
Token::StartTag {
|
vec![
|
||||||
name: "foo".into(),
|
Token::StartTag {
|
||||||
attrs: vec![Attribute {
|
name: "foo".into(),
|
||||||
name: "bar".into(),
|
attrs: vec![Attribute {
|
||||||
value: "baz".to_owned(),
|
name: "bar".into(),
|
||||||
}],
|
value: "baz".to_owned(),
|
||||||
self_closing: false,
|
}],
|
||||||
},
|
self_closing: false,
|
||||||
Token::Text("quux".to_owned()),
|
},
|
||||||
Token::EndTag {
|
Token::Text("quux".to_owned()),
|
||||||
name: "foo".into(),
|
Token::EndTag { name: "foo".into() },
|
||||||
},
|
],
|
||||||
], run(chunk_size, buf));
|
run(chunk_size, buf)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
//! SAX events to DOM tree conversion
|
//! SAX events to DOM tree conversion
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
|
||||||
use crate::{Element, Error};
|
|
||||||
use crate::prefixes::Prefixes;
|
use crate::prefixes::Prefixes;
|
||||||
use crate::token::{Attribute, LocalName, Token};
|
use crate::token::{Attribute, LocalName, Token};
|
||||||
|
use crate::{Element, Error};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// Tree-building parser state
|
/// Tree-building parser state
|
||||||
pub struct TreeBuilder {
|
pub struct TreeBuilder {
|
||||||
|
@ -85,7 +85,8 @@ impl TreeBuilder {
|
||||||
}
|
}
|
||||||
self.prefixes_stack.push(prefixes.clone());
|
self.prefixes_stack.push(prefixes.clone());
|
||||||
|
|
||||||
let namespace = self.lookup_prefix(&name.prefix)
|
let namespace = self
|
||||||
|
.lookup_prefix(&name.prefix)
|
||||||
.ok_or(Error::MissingNamespace)?
|
.ok_or(Error::MissingNamespace)?
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let el = Element::new(
|
let el = Element::new(
|
||||||
|
@ -94,7 +95,7 @@ impl TreeBuilder {
|
||||||
Some(name.prefix),
|
Some(name.prefix),
|
||||||
prefixes,
|
prefixes,
|
||||||
attributes,
|
attributes,
|
||||||
vec![]
|
vec![],
|
||||||
);
|
);
|
||||||
self.stack.push(el);
|
self.stack.push(el);
|
||||||
|
|
||||||
|
@ -128,7 +129,7 @@ impl TreeBuilder {
|
||||||
/// Process a Token that you got out of a Tokenizer
|
/// Process a Token that you got out of a Tokenizer
|
||||||
pub fn process_token(&mut self, token: Token) -> Result<(), Error> {
|
pub fn process_token(&mut self, token: Token) -> Result<(), Error> {
|
||||||
match token {
|
match token {
|
||||||
Token::XmlDecl { .. } => {},
|
Token::XmlDecl { .. } => {}
|
||||||
|
|
||||||
Token::StartTag {
|
Token::StartTag {
|
||||||
name,
|
name,
|
||||||
|
@ -145,11 +146,9 @@ impl TreeBuilder {
|
||||||
self.process_end_tag(name)?;
|
self.process_end_tag(name)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Token::EndTag { name } =>
|
Token::EndTag { name } => self.process_end_tag(name)?,
|
||||||
self.process_end_tag(name)?,
|
|
||||||
|
|
||||||
Token::Text(text) =>
|
Token::Text(text) => self.process_text(text),
|
||||||
self.process_text(text),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -203,30 +203,28 @@ impl Stream for Client {
|
||||||
self.poll_next(cx)
|
self.poll_next(cx)
|
||||||
}
|
}
|
||||||
ClientState::Disconnected => Poll::Ready(None),
|
ClientState::Disconnected => Poll::Ready(None),
|
||||||
ClientState::Connecting(mut connect) => {
|
ClientState::Connecting(mut connect) => match Pin::new(&mut connect).poll(cx) {
|
||||||
match Pin::new(&mut connect).poll(cx) {
|
Poll::Ready(Ok(Ok(stream))) => {
|
||||||
Poll::Ready(Ok(Ok(stream))) => {
|
let bound_jid = stream.jid.clone();
|
||||||
let bound_jid = stream.jid.clone();
|
self.state = ClientState::Connected(stream);
|
||||||
self.state = ClientState::Connected(stream);
|
Poll::Ready(Some(Event::Online {
|
||||||
Poll::Ready(Some(Event::Online {
|
bound_jid,
|
||||||
bound_jid,
|
resumed: false,
|
||||||
resumed: false,
|
}))
|
||||||
}))
|
|
||||||
}
|
|
||||||
Poll::Ready(Ok(Err(e))) => {
|
|
||||||
self.state = ClientState::Disconnected;
|
|
||||||
return Poll::Ready(Some(Event::Disconnected(e.into())));
|
|
||||||
}
|
|
||||||
Poll::Ready(Err(e)) => {
|
|
||||||
self.state = ClientState::Disconnected;
|
|
||||||
panic!("connect task: {}", e);
|
|
||||||
}
|
|
||||||
Poll::Pending => {
|
|
||||||
self.state = ClientState::Connecting(connect);
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
Poll::Ready(Ok(Err(e))) => {
|
||||||
|
self.state = ClientState::Disconnected;
|
||||||
|
return Poll::Ready(Some(Event::Disconnected(e.into())));
|
||||||
|
}
|
||||||
|
Poll::Ready(Err(e)) => {
|
||||||
|
self.state = ClientState::Disconnected;
|
||||||
|
panic!("connect task: {}", e);
|
||||||
|
}
|
||||||
|
Poll::Pending => {
|
||||||
|
self.state = ClientState::Connecting(connect);
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
},
|
||||||
ClientState::Connected(mut stream) => {
|
ClientState::Connected(mut stream) => {
|
||||||
// Poll sink
|
// Poll sink
|
||||||
match Pin::new(&mut stream).poll_ready(cx) {
|
match Pin::new(&mut stream).poll_ready(cx) {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
//! XML stream parser for XMPP
|
//! XML stream parser for XMPP
|
||||||
|
|
||||||
|
use crate::Error;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
use minidom::{tokenize, tree_builder::TreeBuilder};
|
||||||
use std;
|
use std;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -9,8 +11,6 @@ use std::fmt::Write;
|
||||||
use std::io;
|
use std::io;
|
||||||
use tokio_util::codec::{Decoder, Encoder};
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
use xmpp_parsers::Element;
|
use xmpp_parsers::Element;
|
||||||
use minidom::{tokenize, tree_builder::TreeBuilder};
|
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
/// Anything that can be sent or received on an XMPP/XML stream
|
/// Anything that can be sent or received on an XMPP/XML stream
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -60,20 +60,23 @@ impl Decoder for XMPPCodec {
|
||||||
self.stanza_builder.process_token(token)?;
|
self.stanza_builder.process_token(token)?;
|
||||||
let has_stream_root = self.stanza_builder.depth() > 0;
|
let has_stream_root = self.stanza_builder.depth() > 0;
|
||||||
|
|
||||||
if ! had_stream_root && has_stream_root {
|
if !had_stream_root && has_stream_root {
|
||||||
let root = self.stanza_builder.top().unwrap();
|
let root = self.stanza_builder.top().unwrap();
|
||||||
let attrs = root.attrs()
|
let attrs =
|
||||||
.map(|(name, value)| (name.to_owned(), value.to_owned()))
|
root.attrs()
|
||||||
.chain(
|
.map(|(name, value)| (name.to_owned(), value.to_owned()))
|
||||||
root.prefixes.declared_prefixes()
|
.chain(root.prefixes.declared_prefixes().iter().map(
|
||||||
.iter()
|
|(prefix, namespace)| {
|
||||||
.map(|(prefix, namespace)| (
|
(
|
||||||
prefix.as_ref().map(|prefix| format!("xmlns:{}", prefix))
|
prefix
|
||||||
.unwrap_or_else(|| "xmlns".to_owned()),
|
.as_ref()
|
||||||
namespace.clone()
|
.map(|prefix| format!("xmlns:{}", prefix))
|
||||||
))
|
.unwrap_or_else(|| "xmlns".to_owned()),
|
||||||
)
|
namespace.clone(),
|
||||||
.collect();
|
)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.collect();
|
||||||
return Ok(Some(Packet::StreamStart(attrs)));
|
return Ok(Some(Packet::StreamStart(attrs)));
|
||||||
} else if self.stanza_builder.depth() == 1 {
|
} else if self.stanza_builder.depth() == 1 {
|
||||||
if let Some(stanza) = self.stanza_builder.unshift_child() {
|
if let Some(stanza) = self.stanza_builder.unshift_child() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user