diff options
Diffstat (limited to 'src/xml/mod.rs')
-rw-r--r-- | src/xml/mod.rs | 101 |
1 files changed, 94 insertions, 7 deletions
diff --git a/src/xml/mod.rs b/src/xml/mod.rs index 2d20ca0..8fb5419 100644 --- a/src/xml/mod.rs +++ b/src/xml/mod.rs @@ -1,4 +1,6 @@ -use std::{char, ops::Deref}; +use std::{char, convert::Infallible, ops::Deref, str::FromStr}; + +use parsers_complete::Parser; use crate::error::Error; @@ -228,14 +230,14 @@ pub enum EntityValue<'s> { SingleQuoted(Vec<EntityValueData<'s>>), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum AttValueData<'s> { String(&'s str), Reference(Reference<'s>), } /// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' /// | "'" ([^<&'] | Reference)* "'" -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum AttValue<'s> { DoubleQuoted(Vec<AttValueData<'s>>), SingleQuoted(Vec<AttValueData<'s>>), @@ -259,6 +261,34 @@ impl<'s> AttValue<'s> { } } +impl<'s> From<&'s str> for AttValue<'s> { + fn from(s: &'s str) -> AttValue<'s> { + let mut data = Vec::new(); + for str in s.split_inclusive(|c| c == '<' || c == '"') { + if let Some(str) = str.strip_suffix('<') { + if !str.is_empty() { + data.push(AttValueData::String(str)) + } + data.push(AttValueData::Reference(Reference::EntityRef(EntityRef( + Name::parse_full("lt").unwrap(), + )))) + } else if let Some(str) = str.strip_suffix('"') { + if !str.is_empty() { + data.push(AttValueData::String(str)) + } + data.push(AttValueData::Reference(Reference::EntityRef(EntityRef( + Name::parse_full("quot").unwrap(), + )))) + } else { + if !str.is_empty() { + data.push(AttValueData::String(str)) + } + } + } + AttValue::DoubleQuoted(data) + } +} + /// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") #[derive(Debug)] pub enum SystemLiteral<'s> { @@ -673,7 +703,7 @@ pub struct IgnoreSectContents<'s> { pub struct Ignore<'s>(&'s str); /// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum CharRef<'s> { Decimal(&'s str), Hexadecimal(&'s str), @@ -706,7 +736,7 @@ impl<'s> CharRef<'s> { } /// [67] Reference ::= EntityRef | CharRef -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Reference<'s> { EntityRef(EntityRef<'s>), CharRef(CharRef<'s>), @@ -729,8 +759,8 @@ impl<'s> Reference<'s> { } /// [68] EntityRef ::= '&' Name ';' -#[derive(Clone, Debug)] -pub struct EntityRef<'s>(Name<'s>); +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct EntityRef<'s>(pub(crate) Name<'s>); impl<'s> Deref for EntityRef<'s> { type Target = Name<'s>; @@ -835,3 +865,60 @@ pub struct NotationDecl<'s> { /// [83] PublicID ::= 'PUBLIC' S PubidLiteral #[derive(Debug)] pub struct PublicID<'s>(PubidLiteral<'s>); + +#[cfg(test)] +mod test { + use super::{AttValue, AttValueData, EntityRef, Name, Reference}; + + #[test] + fn att_value_from_str() { + assert_eq!( + AttValue::from("hsdaflaskdf<laksdf<abdsf"), + AttValue::DoubleQuoted(vec![ + AttValueData::String("hsdaflaskdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::String("laksdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::String("abdsf"), + ]) + ); + assert_eq!( + AttValue::from("hsdaflaskdf<laksdf\"abdsf"), + AttValue::DoubleQuoted(vec![ + AttValueData::String("hsdaflaskdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::String("laksdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))), + AttValueData::String("abdsf"), + ]) + ); + assert_eq!( + AttValue::from("hsdaflaskdf<laksdf\""), + AttValue::DoubleQuoted(vec![ + AttValueData::String("hsdaflaskdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::String("laksdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))), + ]) + ); + assert_eq!( + AttValue::from("hsdaflaskdf\"<<laksdf\""), + AttValue::DoubleQuoted(vec![ + AttValueData::String("hsdaflaskdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::String("laksdf"), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))), + ]) + ); + assert_eq!( + AttValue::from("<<\""), + AttValue::DoubleQuoted(vec![ + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("lt")))), + AttValueData::Reference(Reference::EntityRef(EntityRef(Name("quot")))), + ]) + ); + } +} |