diff --git a/src/element.rs b/src/element.rs index 7d72315..25c781c 100644 --- a/src/element.rs +++ b/src/element.rs @@ -35,17 +35,17 @@ //! # mode to ensure that it only matches a completely empty message stanza: //! //! Louise receives: -//! +//! //! ``` use std::collections::HashMap; -use std::ops::Deref; use std::fmt::Debug; use std::marker::PhantomData; +use std::ops::Deref; -use crate::{Client, ClientName}; -use crate::types::VariableAttr; use crate::parsers::parse_variable; +use crate::types::VariableAttr; +use crate::{Client, ClientName}; use jid::BareJid; use minidom::{Element, Node}; @@ -84,12 +84,8 @@ impl ScanNode { impl PartialEq for ScanNode { fn eq(&self, other: &Node) -> bool { match (&self.node, other) { - (Node::Text(text1), Node::Text(text2)) => { - text1 == text2 - }, - (Node::Element(elem1), Node::Element(elem2)) => { - ScanElement::new(&elem1) == elem2 - }, + (Node::Text(text1), Node::Text(text2)) => text1 == text2, + (Node::Element(elem1), Node::Element(elem2)) => ScanElement::new(&elem1) == elem2, _ => false, } } @@ -116,46 +112,46 @@ fn filter_whitespace_nodes(nodes: Vec) -> Vec { (Some(type_), acc) }; - let rm_empty_text = |node: &Node| { - match node { - Node::Text(text) => { - text.trim().len() != 0 - }, - _ => true, - } + let rm_empty_text = |node: &Node| match node { + Node::Text(text) => text.trim().len() != 0, + _ => true, }; let nodes = nodes .into_iter() - .fold((None::, vec![]), filter_nodes).1; + .fold((None::, vec![]), filter_nodes) + .1; - // Don't remove possibly significant whitespace text leaves - if nodes.iter().count() == 1 { - nodes - } else { - nodes - .into_iter() - .filter(rm_empty_text) - .collect() - } + // Don't remove possibly significant whitespace text leaves + if nodes.iter().count() == 1 { + nodes + } else { + nodes.into_iter().filter(rm_empty_text).collect() + } } #[derive(Debug)] struct ScanNodes { - nodes: Vec, - _strict: PhantomData, + nodes: Vec, + _strict: PhantomData, } impl ScanNodes { - fn new(nodes: Vec) -> ScanNodes { - Self { nodes, _strict: PhantomData } - } + fn new(nodes: Vec) -> ScanNodes { + Self { + nodes, + _strict: PhantomData, + } + } } impl ScanNodes { - fn new_strict(nodes: Vec) -> ScanNodes { - Self { nodes, _strict: PhantomData } - } + fn new_strict(nodes: Vec) -> ScanNodes { + Self { + nodes, + _strict: PhantomData, + } + } } /// Tags with mixed significant text and children tags aren't valid in XMPP, so we know we can @@ -164,9 +160,9 @@ impl ScanNodes { impl PartialEq> for ScanNodes { fn eq(&self, other: &Vec) -> bool { let filtered_self = filter_whitespace_nodes(self.nodes.clone()) - .into_iter() - .map(ScanNode::new) - .collect::>(); + .into_iter() + .map(ScanNode::new) + .collect::>(); let filtered_other = filter_whitespace_nodes(other.clone()); filtered_self == filtered_other @@ -181,15 +177,15 @@ impl PartialEq> for ScanNodes { let filtered_other = filter_whitespace_nodes(other.clone()); filter_whitespace_nodes(self.nodes.clone()) - .into_iter() - // Maps nodes to their comparison result - .fold(true, |res, node| { - let scan = ScanNode::new(node); - res && - filtered_other.iter().find(|onode| { - &&scan == onode - }).is_some() - }) + .into_iter() + // Maps nodes to their comparison result + .fold(true, |res, node| { + let scan = ScanNode::new(node); + res && filtered_other + .iter() + .find(|onode| &&scan == onode) + .is_some() + }) } } @@ -200,12 +196,12 @@ impl PartialEq> for ScanNodes { /// Also uses the custom ScanNode implementation. #[derive(Debug, Clone)] pub struct ScanElement<'a, 'b> { - elem: &'a Element, - context: Option<&'b HashMap>, + elem: &'a Element, + context: Option<&'b HashMap>, } impl<'a, 'b> Deref for ScanElement<'a, 'b> { - type Target = Element; + type Target = Element; fn deref(&self) -> &Self::Target { &self.elem @@ -213,24 +209,28 @@ impl<'a, 'b> Deref for ScanElement<'a, 'b> { } impl<'a> ScanElement<'a, 'static> { - pub fn new(elem: &'a Element) -> ScanElement { - Self { elem, context: None } - } + pub fn new(elem: &'a Element) -> ScanElement { + Self { + elem, + context: None, + } + } } -impl <'a, 'b> ScanElement<'a, 'b> { - pub fn with_context(self, context: &'b HashMap) -> ScanElement<'a, 'b> { - Self { elem: self.elem, context: Some(context) } - } +impl<'a, 'b> ScanElement<'a, 'b> { + pub fn with_context(self, context: &'b HashMap) -> ScanElement<'a, 'b> { + Self { + elem: self.elem, + context: Some(context), + } + } } impl<'a, 'b> PartialEq<&Element> for ScanElement<'a, 'b> { fn eq(&self, other: &&Element) -> bool { let self_ns = self.elem.ns(); - if self.elem.name() == other.name() && - self_ns == other.ns() { - - let strict_attr = self.elem.attr("scansion:strict"); + if self.elem.name() == other.name() && self_ns == other.ns() { + let strict_attr = self.elem.attr("scansion:strict"); // Force true if scansion:strict is set or if a tag isn't in the default ns. let strict = if let Some(val) = strict_attr { @@ -239,14 +239,14 @@ impl<'a, 'b> PartialEq<&Element> for ScanElement<'a, 'b> { self_ns != DEFAULT_NS }; - for (attr, val) in self.elem.attrs() { - if val == "{scansion:any}" { - continue; - } + for (attr, val) in self.elem.attrs() { + if val == "{scansion:any}" { + continue; + } - // Parse variables. If parsing fails, continue attr comparison. - // If context isn't set, skip this and continue attr comparison. - if let Ok((_, var)) = parse_variable(val.into()) && + // Parse variables. If parsing fails, continue attr comparison. + // If context isn't set, skip this and continue attr comparison. + if let Ok((_, var)) = parse_variable(val.into()) && let Some(context) = self.context { let res = match var { VariableAttr::FullJid(name) => match context.get(&name) { @@ -266,33 +266,33 @@ impl<'a, 'b> PartialEq<&Element> for ScanElement<'a, 'b> { } } - match (attr, other.attr(attr)) { - (attr, _) if attr == "scansion:strict" => continue, - (_, None) => return false, - (_, Some(oval)) if val != oval => return false, - _ => (), - } - } + match (attr, other.attr(attr)) { + (attr, _) if attr == "scansion:strict" => continue, + (_, None) => return false, + (_, Some(oval)) if val != oval => return false, + _ => (), + } + } - let onodes = other.nodes().cloned().collect::>(); + let onodes = other.nodes().cloned().collect::>(); - // Compare attributes count - if strict { - let count = self.elem.attrs().into_iter().count(); - let ocount = other.attrs().into_iter().count(); + // Compare attributes count + if strict { + let count = self.elem.attrs().into_iter().count(); + let ocount = other.attrs().into_iter().count(); - match strict_attr { - None if count != ocount => return false, - Some(_) if count != ocount + 1 => return false, - _ => (), - } + match strict_attr { + None if count != ocount => return false, + Some(_) if count != ocount + 1 => return false, + _ => (), + } - let nodes = ScanNodes::new_strict(self.elem.nodes().cloned().collect()); - nodes == onodes - } else { - let nodes = ScanNodes::new(self.elem.nodes().cloned().collect()); - nodes == onodes - } + let nodes = ScanNodes::new_strict(self.elem.nodes().cloned().collect()); + nodes == onodes + } else { + let nodes = ScanNodes::new(self.elem.nodes().cloned().collect()); + nodes == onodes + } } else { false } @@ -304,6 +304,8 @@ mod tests { use super::*; use std::str::FromStr; + use jid::Jid; + #[test] fn compare_nodes_simple() { let text1 = Node::Text(String::from("\t\t")); @@ -360,7 +362,9 @@ mod tests { #[test] fn compare_element_non_strict_whitespace_success() { - let elem1: Element = "\n\t".parse().unwrap(); + let elem1: Element = "\n\t" + .parse() + .unwrap(); let elem2: Element = "".parse().unwrap(); let scan1 = ScanElement::new(&elem1); @@ -369,8 +373,12 @@ mod tests { #[test] fn compare_element_non_strict_whitespace_failure() { - let elem1: Element = "\n\tfoo".parse().unwrap(); - let elem2: Element = "\n\tfoo\t".parse().unwrap(); + let elem1: Element = "\n\tfoo" + .parse() + .unwrap(); + let elem2: Element = "\n\tfoo\t" + .parse() + .unwrap(); let scan1 = ScanElement::new(&elem1); assert_ne!(scan1, &elem2); @@ -384,11 +392,15 @@ mod tests { assert_eq!(scan1, &elem1); let elem2: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let elem3: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let scan2 = ScanElement::new(&elem2); assert_eq!(scan2, &elem3); @@ -406,18 +418,22 @@ mod tests { #[test] fn compare_element_strict_nodes_success() { let elem1: Element = " - + - ".parse().unwrap(); - // The same, minus 'scansion:strict' + " + .parse() + .unwrap(); + // The same, minus 'scansion:strict' let elem2: Element = " - + - ".parse().unwrap(); + " + .parse() + .unwrap(); let scan1 = ScanElement::new(&elem1); assert_eq!(scan1, &elem2); @@ -426,15 +442,19 @@ mod tests { #[test] fn compare_element_strict_nodes_failure() { let elem1: Element = " - + - ".parse().unwrap(); + " + .parse() + .unwrap(); let elem2: Element = " - + - ".parse().unwrap(); + " + .parse() + .unwrap(); let scan1 = ScanElement::new(&elem1); assert_ne!(scan1, &elem2); @@ -442,17 +462,23 @@ mod tests { #[test] fn compare_element_non_strict_attributes_success() { - let elem1: Element = "".parse().unwrap(); + let elem1: Element = "" + .parse() + .unwrap(); let scan1 = ScanElement::new(&elem1); assert_eq!(scan1, &elem1); let elem2: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let elem3: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let scan2 = ScanElement::new(&elem2); assert_eq!(scan2, &elem3); @@ -460,18 +486,24 @@ mod tests { #[test] fn compare_element_non_strict_attributes_failure() { - let elem1: Element = "".parse().unwrap(); + let elem1: Element = "" + .parse() + .unwrap(); let elem2: Element = "".parse().unwrap(); let scan1 = ScanElement::new(&elem1); assert_ne!(scan1, &elem2); let elem2: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let elem3: Element = " - - ".parse().unwrap(); + + " + .parse() + .unwrap(); let scan2 = ScanElement::new(&elem2); assert_ne!(scan2, &elem3); @@ -479,15 +511,19 @@ mod tests { #[test] fn compare_element_non_strict_elem_success() { - let elem1: Element = "".parse().unwrap(); + let elem1: Element = "" + .parse() + .unwrap(); let elem2: Element = "".parse().unwrap(); let scan1 = ScanElement::new(&elem1); assert_eq!(scan1, &elem2); - // 'jabber:client' is non strict by default + // 'jabber:client' is non strict by default let elem3: Element = "".parse().unwrap(); - let elem4: Element = "".parse().unwrap(); + let elem4: Element = "" + .parse() + .unwrap(); let scan3 = ScanElement::new(&elem3); assert_eq!(scan3, &elem4); @@ -496,54 +532,66 @@ mod tests { #[test] fn compare_element_non_strict_elem_failure() { let elem2: Element = " - foo - ".parse().unwrap(); + foo + " + .parse() + .unwrap(); let elem3: Element = " - bar - ".parse().unwrap(); + bar + " + .parse() + .unwrap(); let scan2 = ScanElement::new(&elem2); assert_ne!(scan2, &elem3); } - #[test] - fn compare_element_propagate_strictness() { + #[test] + fn compare_element_propagate_strictness() { let elem1: Element = " - ".parse().unwrap(); + " + .parse() + .unwrap(); let elem2: Element = " - ".parse().unwrap(); + " + .parse() + .unwrap(); let scan1 = ScanElement::new(&elem1); assert_ne!(scan1, &elem2); - } + } - #[test] - fn ignore_attr_val_success() { - let elem1: Element = "" - .parse().unwrap(); - let elem2: Element = "".parse().unwrap(); - let scan1 = ScanElement::new(&elem1); + #[test] + fn ignore_attr_val_success() { + let elem1: Element = "" + .parse() + .unwrap(); + let elem2: Element = "".parse().unwrap(); + let scan1 = ScanElement::new(&elem1); - assert_eq!(scan1, &elem2); - } + assert_eq!(scan1, &elem2); + } - #[test] - fn variables_from_context() { - let louise = Client::new(Jid::from_str("louise@example.com").unwrap(), "passwd"); + #[test] + fn variables_from_context() { + let louise = Client::new(Jid::from_str("louise@example.com").unwrap(), "passwd"); - let clients = { - let mut tmp = HashMap::new(); - tmp.insert(String::from("louise"), louise); - tmp - }; + let clients = { + let mut tmp = HashMap::new(); + tmp.insert(String::from("louise"), louise); + tmp + }; - let elem1: Element = "" - .parse().unwrap(); - let elem2: Element = "".parse().unwrap(); - let scan1 = ScanElement::new(&elem1).with_context(&clients); + let elem1: Element = "" + .parse() + .unwrap(); + let elem2: Element = "" + .parse() + .unwrap(); + let scan1 = ScanElement::new(&elem1).with_context(&clients); - assert_eq!(scan1, &elem2); - } + assert_eq!(scan1, &elem2); + } } diff --git a/src/parsers.rs b/src/parsers.rs index fbc4795..7baf77d 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -4,7 +4,7 @@ // 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/. -use crate::types::{Action, Client, ClientName, Metadata, VariableAttr, Spec}; +use crate::types::{Action, Client, ClientName, Metadata, Spec, VariableAttr}; use std::collections::HashMap; use std::str::FromStr; @@ -280,22 +280,21 @@ pub fn parse_spec(i: &str) -> Result { } pub fn parse_variable(s: Span) -> IResult { - let (s, (_, name, attr, _)) = tuple(( - tag("${"), take_until_tags(vec![ - "'s full JID", - "'s JID", - ].into_iter(), - "}", - ), - alt((tag("'s full JID"), tag("'s JID"))), - tag("}"), - ))(s)?; + let (s, (_, name, attr, _)) = tuple(( + tag("${"), + take_until_tags(vec!["'s full JID", "'s JID"].into_iter(), "}"), + alt((tag("'s full JID"), tag("'s JID"))), + tag("}"), + ))(s)?; - Ok((s, match *attr.fragment() { - "'s full JID" => VariableAttr::FullJid(name.to_string()), - "'s JID" => VariableAttr::BareJid(name.to_string()), - _ => unreachable!(), - })) + Ok(( + s, + match *attr.fragment() { + "'s full JID" => VariableAttr::FullJid(name.to_string()), + "'s JID" => VariableAttr::BareJid(name.to_string()), + _ => unreachable!(), + }, + )) } #[cfg(test)] @@ -622,28 +621,28 @@ louise receives: ); } - #[test] - fn parse_variable_attr() { - let buf1: Span = "${louise's full JID}".into(); - let buf2: Span = "${louise's JID}".into(); - let buf3: Span = "${louise's JID".into(); + #[test] + fn parse_variable_attr() { + let buf1: Span = "${louise's full JID}".into(); + let buf2: Span = "${louise's JID}".into(); + let buf3: Span = "${louise's JID".into(); - assert_eq!( - parse_variable(buf1).unwrap().1, - VariableAttr::FullJid(String::from("louise")), - ); + assert_eq!( + parse_variable(buf1).unwrap().1, + VariableAttr::FullJid(String::from("louise")), + ); - assert_eq!( - parse_variable(buf2).unwrap().1, - VariableAttr::BareJid(String::from("louise")), - ); + assert_eq!( + parse_variable(buf2).unwrap().1, + VariableAttr::BareJid(String::from("louise")), + ); - match parse_variable(buf3) { - Err(nom::Err::Error(nom::error::Error { input, .. })) => { - assert_eq!(input.location_offset(), 2); - assert_eq!(input.location_line(), 1); - } - err => panic!("Expected Err, found: {err:?}"), - } - } + match parse_variable(buf3) { + Err(nom::Err::Error(nom::error::Error { input, .. })) => { + assert_eq!(input.location_offset(), 2); + assert_eq!(input.location_line(), 1); + } + err => panic!("Expected Err, found: {err:?}"), + } + } } diff --git a/src/types.rs b/src/types.rs index 6bb5877..661219e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,8 +10,8 @@ use jid::Jid; #[derive(Debug, PartialEq)] pub enum VariableAttr { - FullJid(ClientName), - BareJid(ClientName), + FullJid(ClientName), + BareJid(ClientName), } #[derive(Debug, Clone, PartialEq)]