use std::collections::HashMap;
#[derive(Debug, PartialEq, Clone)]
pub struct Tag {
name: String,
attrs: Option<HashMap<String, String>>,
terminated: bool,
terminator: bool,
}
impl Tag {
pub fn new(name: &str) -> Tag {
Tag {
name: String::from(name),
attrs: None,
terminated: false,
terminator: false,
}
}
pub fn get_name(&self) -> &str {
&self.name
}
pub fn set_attrs(&mut self, attrs: HashMap<String, String>) {
self.attrs = Some(attrs);
}
pub fn get_attrs(&self) -> Option<&HashMap<String, String>> {
self.attrs.as_ref()
}
pub fn set_attr(&mut self, attr: &str, value: &str) {
match self.attrs.as_mut() {
Some(attrs) => {
attrs.insert(String::from(attr), String::from(value));
}
None => {
let mut attrs = HashMap::new();
attrs.insert(String::from(attr), String::from(value));
self.attrs = Some(attrs);
}
};
}
pub fn get_attr(&self, attr: &str) -> Option<String> {
if let Some(attrs) = &self.attrs {
if let Some(v) = attrs.get(attr) {
return Some(v.to_string());
}
}
None
}
pub fn set_terminated(&mut self, b: bool) {
self.terminated = b;
}
pub fn is_terminated(&self) -> bool {
self.terminated
}
pub fn set_terminator(&mut self, b: bool) {
self.terminator = b;
}
pub fn is_terminator(&self) -> bool {
self.terminator
}
pub fn p_implies_q(p: &Tag, q: &Tag) -> bool {
let mut satisfied = false;
if q.get_name() == p.get_name() {
satisfied = true;
}
if satisfied {
if let Some(p_attrs) = p.get_attrs() {
match q.get_attrs() {
Some(q_attrs) => {
for (p_key, p_value) in p_attrs.iter() {
match q_attrs.get(p_key) {
Some(q_value) => {
if p_value != "" && p_value != q_value {
satisfied = false;
break;
}
}
None => {
satisfied = false;
break;
}
}
}
}
None => satisfied = false,
}
}
}
satisfied
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_empty_attr() {
let tag = Tag::new("h1");
assert_eq!(None, tag.get_attr("class"));
}
#[test]
fn set_attr() {
let mut tag = Tag::new("h1");
tag.set_attr("class", "section1");
assert_eq!(Some("section1".to_string()), tag.get_attr("class"));
assert_eq!(None, tag.get_attr("id"));
}
#[test]
fn sufficient_condition() {
let mut p = Tag::new("h1");
p.set_attr("class", "target");
let mut q = Tag::new("h1");
q.set_attr("id", "q");
q.set_attr("class", "target");
assert_eq!(Tag::p_implies_q(&p, &q), true);
}
#[test]
fn not_sufficient_condition() {
let mut p = Tag::new("h1");
p.set_attr("class", "target");
let mut q = Tag::new("h1");
q.set_attr("id", "q");
assert_eq!(Tag::p_implies_q(&p, &q), false);
}
#[test]
fn eq_test() {
let mut a = Tag::new("h1");
a.set_attr("id", "idA");
a.set_attr("class", "classA");
let mut b = Tag::new("h1");
b.set_attr("id", "idA");
b.set_attr("class", "classA");
assert_eq!(a == b, true);
assert_eq!(a != b, false);
}
#[test]
fn ne_test() {
let mut a = Tag::new("h1");
a.set_attr("id", "idA");
a.set_attr("class", "classA");
let mut b = Tag::new("h2");
b.set_attr("id", "idB");
b.set_attr("class", "classB");
assert_eq!(a == b, false);
assert_eq!(a != b, true);
}
}