Don't convert XML to minidom::Element anymore
Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
parent
309be31d45
commit
e9c6d32445
4 changed files with 25 additions and 46 deletions
|
@ -9,7 +9,6 @@ description = "Parser for the Scansion DSL"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
nom = "7.1"
|
nom = "7.1"
|
||||||
jid = "0.9"
|
jid = "0.9"
|
||||||
minidom = "0.15.1"
|
|
||||||
nom_locate = "4.0.0"
|
nom_locate = "4.0.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -7,5 +7,8 @@
|
||||||
mod parsers;
|
mod parsers;
|
||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
|
pub static DEFAULT_NS: &str = "jabber:client";
|
||||||
|
pub static SCANSION_NS: &str = "https://matthewwild.co.uk/projects/scansion";
|
||||||
|
|
||||||
pub use parsers::parse_spec;
|
pub use parsers::parse_spec;
|
||||||
pub use types::{Spec, Action, Client, Metadata};
|
pub use types::{Action, Client, Metadata, Spec};
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use crate::types::{Spec, Action, Client, ClientName, Metadata};
|
use crate::types::{Action, Client, ClientName, Metadata, Spec};
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap};
|
use std::collections::HashMap;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use jid::Jid;
|
use jid::Jid;
|
||||||
use minidom::Element;
|
|
||||||
use nom::{
|
use nom::{
|
||||||
self,
|
self,
|
||||||
branch::alt,
|
branch::alt,
|
||||||
|
@ -42,9 +41,6 @@ impl<'a> From<NomErr<nom::error::Error<LocatedSpan<&'a str>>>> for Token<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static DEFAULT_NS: &str = "jabber:client";
|
|
||||||
pub static SCANSION_NS: &str = "https://matthewwild.co.uk/projects/scansion";
|
|
||||||
|
|
||||||
fn allspaces(s: Span) -> IResult<Span, Token> {
|
fn allspaces(s: Span) -> IResult<Span, Token> {
|
||||||
let (s, (pos, _, comments)) = tuple((position, multispace0, opt(comment)))(s)?;
|
let (s, (pos, _, comments)) = tuple((position, multispace0, opt(comment)))(s)?;
|
||||||
|
|
||||||
|
@ -247,21 +243,20 @@ fn parse_action_subline(s: Span) -> IResult<Span, &str> {
|
||||||
Ok((s, line.fragment()))
|
Ok((s, line.fragment()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_send_receive<'a>(tagname: &str, name: String, s: Span<'a>) -> IResult<Span<'a>, Action> {
|
fn parse_send_receive<'a>(
|
||||||
|
tagname: &str,
|
||||||
|
name: String,
|
||||||
|
s: Span<'a>,
|
||||||
|
) -> IResult<Span<'a>, Action<'a>> {
|
||||||
let (s, (_, lines)) = tuple((
|
let (s, (_, lines)) = tuple((
|
||||||
take_while(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
|
take_while(|c| c == ' ' || c == '\r' || c == '\n'), // Spaces but \t
|
||||||
recognize(many1(parse_action_subline)),
|
recognize(many1(parse_action_subline)),
|
||||||
))(s)?;
|
))(s)?;
|
||||||
let lines = lines.trim();
|
let lines = lines.trim();
|
||||||
|
|
||||||
// Namespaces
|
|
||||||
let mut prefixes = BTreeMap::new();
|
|
||||||
prefixes.insert(None, String::from(DEFAULT_NS));
|
|
||||||
prefixes.insert(Some(String::from("scansion")), String::from(SCANSION_NS));
|
|
||||||
let elem: Element = Element::from_reader_with_prefixes(lines.as_bytes(), prefixes).unwrap();
|
|
||||||
Ok(match tagname {
|
Ok(match tagname {
|
||||||
"sends:" => (s, Action::Send(name, elem)),
|
"sends:" => (s, Action::Send(name, lines.clone())),
|
||||||
"receives:" => (s, Action::Receive(name, elem)),
|
"receives:" => (s, Action::Receive(name, lines)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -493,11 +488,9 @@ mod tests {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
let xml = b"<presence\n\t\ttype=\"unavailable\"\t\n/>";
|
|
||||||
|
|
||||||
let send = Action::Send(
|
let send = Action::Send(
|
||||||
String::from("rosa"),
|
String::from("rosa"),
|
||||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
"<presence\n\t\ttype=\"unavailable\"\n\t/>",
|
||||||
);
|
);
|
||||||
assert_eq!(parse_action(buf.into()).unwrap().1, send);
|
assert_eq!(parse_action(buf.into()).unwrap().1, send);
|
||||||
}
|
}
|
||||||
|
@ -511,11 +504,9 @@ mod tests {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
"#;
|
"#;
|
||||||
let xml = b"<presence\n\t\ttype=\"unavailable\"\t\n/>";
|
|
||||||
|
|
||||||
let receive = Action::Receive(
|
let receive = Action::Receive(
|
||||||
String::from("rosa"),
|
String::from("rosa"),
|
||||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
"<presence\n\t\ttype=\"unavailable\"\n\t/>",
|
||||||
);
|
);
|
||||||
assert_eq!(parse_action(buf.into()).unwrap().1, receive);
|
assert_eq!(parse_action(buf.into()).unwrap().1, receive);
|
||||||
}
|
}
|
||||||
|
@ -523,16 +514,9 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_actions_take_until() {
|
fn test_actions_take_until() {
|
||||||
let buf = "Rosa receives:\n\t<presence/>\n\n\n# Comment\n\nPeter sends:\n\t<presence/>\n";
|
let buf = "Rosa receives:\n\t<presence/>\n\n\n# Comment\n\nPeter sends:\n\t<presence/>\n";
|
||||||
let xml = b"<presence/>";
|
|
||||||
let actions = vec![
|
let actions = vec![
|
||||||
Action::Receive(
|
Action::Receive(String::from("Rosa"), "<presence/>"),
|
||||||
String::from("Rosa"),
|
Action::Send(String::from("Peter"), "<presence/>"),
|
||||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
|
||||||
),
|
|
||||||
Action::Send(
|
|
||||||
String::from("Peter"),
|
|
||||||
Element::from_reader_with_prefixes(&xml[..], String::from(DEFAULT_NS)).unwrap(),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
assert_eq!(parse_actions(buf.into()).unwrap().1, actions);
|
assert_eq!(parse_actions(buf.into()).unwrap().1, actions);
|
||||||
}
|
}
|
||||||
|
@ -576,18 +560,12 @@ louise receives:
|
||||||
let mut clients: HashMap<ClientName, Client> = HashMap::new();
|
let mut clients: HashMap<ClientName, Client> = HashMap::new();
|
||||||
clients.insert(String::from("louise"), get_client("louise"));
|
clients.insert(String::from("louise"), get_client("louise"));
|
||||||
|
|
||||||
let xml1 = b"<presence to=\"some@room\" />\n\n";
|
|
||||||
let xml2 = b"<message from=\"louise@localhost\"\n\t\t/>\n\n";
|
|
||||||
|
|
||||||
let actions = vec![
|
let actions = vec![
|
||||||
Action::Connect(String::from("louise")),
|
Action::Connect(String::from("louise")),
|
||||||
Action::Send(
|
Action::Send(String::from("louise"), "<presence to=\"some@room\" />"),
|
||||||
String::from("louise"),
|
|
||||||
Element::from_reader_with_prefixes(&xml1[..], String::from(DEFAULT_NS)).unwrap(),
|
|
||||||
),
|
|
||||||
Action::Receive(
|
Action::Receive(
|
||||||
String::from("louise"),
|
String::from("louise"),
|
||||||
Element::from_reader_with_prefixes(&xml2[..], String::from(DEFAULT_NS)).unwrap(),
|
"<message from=\"louise@localhost\"\n\t\t/>",
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
13
src/types.rs
13
src/types.rs
|
@ -4,9 +4,8 @@
|
||||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use jid::Jid;
|
use jid::Jid;
|
||||||
use minidom::Element;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
|
@ -62,17 +61,17 @@ impl Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Action {
|
pub enum Action<'a> {
|
||||||
Connect(ClientName),
|
Connect(ClientName),
|
||||||
Send(ClientName, Element),
|
Send(ClientName, &'a str),
|
||||||
Receive(ClientName, Element),
|
Receive(ClientName, &'a str),
|
||||||
ReceiveNone(ClientName),
|
ReceiveNone(ClientName),
|
||||||
Disconnect(ClientName),
|
Disconnect(ClientName),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Spec {
|
pub struct Spec<'a> {
|
||||||
pub metadata: Option<Metadata>,
|
pub metadata: Option<Metadata>,
|
||||||
pub clients: HashMap<ClientName, Client>,
|
pub clients: HashMap<ClientName, Client>,
|
||||||
pub actions: Vec<Action>,
|
pub actions: Vec<Action<'a>>,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue