Don't convert XML to minidom::Element anymore

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
This commit is contained in:
Maxime “pep” Buquet 2023-01-17 18:46:38 +01:00
parent 309be31d45
commit e9c6d32445
Signed by: pep
GPG key ID: DEDA74AEECA9D0F2
4 changed files with 25 additions and 46 deletions

View file

@ -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]

View file

@ -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};

View file

@ -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/>",
), ),
]; ];

View file

@ -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>>,
} }