use std::{char, convert::Infallible, ops::Deref, str::FromStr}; use parsers_complete::Parser; use crate::error::{CharRefError, Error}; pub mod composers; pub mod parsers; pub mod parsers_complete; /// [1] NSAttName ::= PrefixedAttName | DefaultAttName #[derive(Clone, Debug)] pub enum NSAttName<'s> { PrefixedAttName(PrefixedAttName<'s>), DefaultAttName, } /// [2] PrefixedAttName ::= 'xmlns:' NCName #[derive(Clone, Debug)] pub struct PrefixedAttName<'s>(pub NCName<'s>); impl<'s> Deref for PrefixedAttName<'s> { type Target = NCName<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [3] DefaultAttName ::= 'xmlns'; #[derive(Clone, Debug)] pub struct DefaultAttName; /// [4] NCName ::= Name - (Char* ':' Char*) #[derive(Clone, Debug, PartialEq, Eq)] pub struct NCName<'s>(&'s str); impl<'s> Deref for NCName<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [7] QName ::= PrefixedName | UnprefixedName #[derive(Clone, Debug, PartialEq, Eq)] pub enum QName<'s> { PrefixedName(PrefixedName<'s>), UnprefixedName(UnprefixedName<'s>), } impl<'s> QName<'s> { pub fn prefix(&self) -> Option<&'s str> { match self { QName::PrefixedName(prefixed_name) => return Some(**prefixed_name.prefix), QName::UnprefixedName(_) => return None, } } pub fn local_part(&self) -> &str { match self { QName::PrefixedName(prefixed_name) => return **prefixed_name.local_part, QName::UnprefixedName(unprefixed_name) => return ****unprefixed_name, } } } impl<'s> ToString for QName<'s> { fn to_string(&self) -> String { match self { QName::PrefixedName(prefixed_name) => { format!("{}:{}", **prefixed_name.prefix, **prefixed_name.local_part) } QName::UnprefixedName(unprefixed_name) => unprefixed_name.to_string(), } } } /// [8] PrefixedName ::= Prefix ':' LocalPart #[derive(Clone, Debug, PartialEq, Eq)] pub struct PrefixedName<'s> { pub(crate) prefix: Prefix<'s>, pub(crate) local_part: LocalPart<'s>, } /// [9] UnprefixedName ::= LocalPart #[derive(Clone, Debug, PartialEq, Eq)] pub struct UnprefixedName<'s>(LocalPart<'s>); impl<'s> Deref for UnprefixedName<'s> { type Target = LocalPart<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [10] Prefix ::= NCName #[derive(Clone, Debug, PartialEq, Eq)] pub struct Prefix<'s>(NCName<'s>); impl<'s> Deref for Prefix<'s> { type Target = NCName<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [11] LocalPart ::= NCName #[derive(Clone, Debug, PartialEq, Eq)] pub struct LocalPart<'s>(NCName<'s>); impl<'s> Deref for LocalPart<'s> { type Target = NCName<'s>; fn deref(&self) -> &Self::Target { &self.0 } } // xml spec /// [1] document ::= prolog element Misc* pub type Document<'s> = (Prolog<'s>, Element<'s>, Vec>); /// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ #[repr(transparent)] pub struct Char(char); impl Deref for Char { type Target = char; fn deref(&self) -> &Self::Target { &self.0 } } /// [3] S ::= (#x20 | #x9 | #xD | #xA)+ #[derive(Clone)] #[repr(transparent)] pub struct S; /// [4] NameStartChar ::= ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF] #[repr(transparent)] pub struct NameStartChar(char); impl Deref for NameStartChar { type Target = char; fn deref(&self) -> &Self::Target { &self.0 } } /// [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040] #[repr(transparent)] pub struct NameChar(char); impl Deref for NameChar { type Target = char; fn deref(&self) -> &Self::Target { &self.0 } } /// [5] Name ::= NameStartChar (NameChar)* #[derive(Debug, Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Name<'s>(&'s str); impl<'s> Deref for Name<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [6] Names ::= Name (#x20 Name)* #[repr(transparent)] pub struct Names<'s>(Vec>); impl<'s> Deref for Names<'s> { type Target = Vec>; fn deref(&self) -> &Self::Target { &self.0 } } /// [7] Nmtoken ::= (NameChar)+ #[derive(Debug, Clone)] #[repr(transparent)] pub struct Nmtoken<'s>(&'s str); impl<'s> Deref for Nmtoken<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)* #[repr(transparent)] pub struct Nmtokens<'s>(Vec>); impl<'s> Deref for Nmtokens<'s> { type Target = Vec>; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Clone, Debug)] pub enum EntityValueData<'s> { String(&'s str), PEReference(PEReference<'s>), Reference(Reference<'s>), } /// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"' /// | "'" ([^%&'] | PEReference | Reference)* "'" #[derive(Debug)] pub enum EntityValue<'s> { DoubleQuoted(Vec>), SingleQuoted(Vec>), } #[derive(Clone, Debug, PartialEq, Eq)] pub enum AttValueData<'s> { String(&'s str), Reference(Reference<'s>), } /// [10] AttValue ::= '"' ([^<&"] | Reference)* '"' /// | "'" ([^<&'] | Reference)* "'" #[derive(Clone, Debug, PartialEq, Eq)] pub enum AttValue<'s> { DoubleQuoted(Vec>), SingleQuoted(Vec>), } impl<'s> AttValue<'s> { pub fn process(&self) -> crate::Result { let mut output = String::new(); let data; match self { AttValue::DoubleQuoted(vec) => data = vec, AttValue::SingleQuoted(vec) => data = vec, } for data in data { match data { AttValueData::String(s) => output.push_str(s), AttValueData::Reference(reference) => output.push(reference.process()?), } } Ok(output) } } 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> { DoubleQuoted(&'s str), SingleQuoted(&'s str), } /// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'" #[derive(Debug)] pub enum PubidLiteral<'s> { DoubleQuoted(&'s str), SingleQuoted(&'s str), } /// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] #[repr(transparent)] pub struct PubidChar(char); /// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct CharData<'s>(&'s str); impl<'s> Deref for CharData<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [15] Comment ::= '' #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct Comment<'s>(&'s str); impl<'s> Deref for Comment<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [16] PI ::= '' Char*)))? '?>' #[derive(Clone, Debug)] pub struct PI<'s> { target: PITarget<'s>, instruction: Option<&'s str>, } /// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l')) #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct PITarget<'s>(Name<'s>); /// [18] CDSect ::= CDStart CData CDEnd #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct CDSect<'s>(CData<'s>); impl<'s> Deref for CDSect<'s> { type Target = CData<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [19] CDStart ::= '' Char*)) #[derive(Clone, Debug, PartialEq, Eq)] #[repr(transparent)] pub struct CData<'s>(&'s str); impl<'s> Deref for CData<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } /// [21] CDEnd ::= ']]>' #[derive(Clone, Debug, PartialEq, Eq)] pub struct CDEnd; /// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)? pub type Prolog<'s> = ( Option>, Vec>, Option<(DoctypeDecl<'s>, Vec>)>, ); /// [23] XMLDecl ::= '' #[derive(Debug)] pub struct XMLDecl<'s> { pub(crate) version_info: VersionInfo, pub(crate) encoding_decl: Option>, pub(crate) sd_decl: Option, } /// [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"') #[derive(Debug)] pub enum VersionInfo { SingleQuoted(VersionNum), DoubleQuoted(VersionNum), } impl Deref for VersionInfo { type Target = VersionNum; fn deref(&self) -> &Self::Target { match self { VersionInfo::SingleQuoted(version_num) => version_num, VersionInfo::DoubleQuoted(version_num) => version_num, } } } /// [25] Eq ::= S? '=' S? #[derive(Clone)] pub struct Eq; /// [26] VersionNum ::= '1.' [0-9]+ #[derive(Clone, Debug)] pub enum VersionNum { One, OneDotOne, } /// [27] Misc ::= Comment | PI | S #[derive(Clone, Debug)] pub enum Misc<'s> { Comment(Comment<'s>), PI(PI<'s>), // TODO: how to deal with whitespace S, } /// [16] doctypedecl ::= '' /// [28] doctypedecl ::= '' #[derive(Debug)] pub struct DoctypeDecl<'s> { name: QName<'s>, external_id: Option>, int_subset: Option>, } /// [28a] DeclSep ::= PEReference | S #[derive(Clone, Debug)] pub enum DeclSep<'s> { PEReference(PEReference<'s>), // TODO: tackle whitespace S, } #[derive(Debug)] pub enum IntSubsetDeclaration<'s> { MarkupDecl(MarkupDecl<'s>), DeclSep(DeclSep<'s>), } /// from [16] intSubset ::= (markupdecl | PEReference | S)* /// [28b] intSubset ::= (markupdecl | DeclSep)* pub type IntSubset<'s> = Vec>; /// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment #[derive(Debug)] pub enum MarkupDecl<'s> { Elementdecl(Elementdecl<'s>), AttlistDecl(AttlistDecl<'s>), EntityDecl(EntityDecl<'s>), NotationDecl(NotationDecl<'s>), PI(PI<'s>), Comment(Comment<'s>), } /// [30] extSubset ::= TextDecl? extSubsetDecl pub struct ExtSubset<'s> { text_decl: Option>, ext_subset_decl: ExtSubsetDecl<'s>, } pub enum ExtSubsetDeclaration<'s> { MarkupDecl(MarkupDecl<'s>), ConditionalSect(ConditionalSect<'s>), DeclSep(DeclSep<'s>), } /// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* type ExtSubsetDecl<'s> = Vec>; /// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"')) #[derive(Debug, Clone)] pub enum SDDecl { SingleQuoted(bool), DoubleQuoted(bool), } impl Deref for SDDecl { type Target = bool; fn deref(&self) -> &Self::Target { match self { SDDecl::SingleQuoted(b) => b, SDDecl::DoubleQuoted(b) => b, } } } // (Productions 33 through 38 have been removed.) /// [39] element ::= EmptyElemTag | STag content ETag #[derive(Debug, Clone)] pub enum Element<'s> { Empty(EmptyElemTag<'s>), NotEmpty(STag<'s>, Content<'s>, ETag<'s>), } /// [12] STag ::= '<' QName (S Attribute)* S? '>' /// [40] STag ::= '<' Name (S Attribute)* S? '>' #[derive(Debug, Clone)] pub struct STag<'s> { pub(crate) name: QName<'s>, pub(crate) attributes: Vec>, } /// [15] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue // pub type Attribute<'s> = (Name<'s>, AttValue<'s>); /// [41] Attribute ::= Name Eq AttValue #[derive(Debug, Clone)] pub enum Attribute<'s> { NamespaceDeclaration { ns_name: NSAttName<'s>, value: AttValue<'s>, }, Attribute { name: QName<'s>, value: AttValue<'s>, }, } /// [13] ETag ::= '' /// [42] ETag ::= '' #[derive(Debug, Clone)] pub struct ETag<'s> { pub(crate) name: QName<'s>, } #[derive(Debug, Clone)] pub enum ContentItem<'s> { // CharData(CharData<'s>), Element(Element<'s>), Reference(Reference<'s>), CDSect(CDSect<'s>), PI(PI<'s>), Comment(Comment<'s>), } /// [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)* #[derive(Debug, Clone)] pub struct Content<'s> { pub(crate) char_data: Option>, pub(crate) content: Vec<(ContentItem<'s>, Option>)>, } /// [14] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>' /// [44] EmptyElemTag ::= '<' Name (S Attribute)* S? '/>' [WFC: Unique Att Spec] #[derive(Debug, Clone)] pub struct EmptyElemTag<'s> { pub(crate) name: QName<'s>, pub(crate) attributes: Vec>, } /// [17] elementdecl ::= '' /// [45] elementdecl ::= '' #[derive(Debug)] pub struct Elementdecl<'s> { name: QName<'s>, contentspec: Contentspec<'s>, } // TODO: casings??? // TODO: wtf does that todo mean? /// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children #[derive(Clone, Debug)] pub enum Contentspec<'s> { Empty, Any, Mixed(Mixed<'s>), Children(Children<'s>), } /// Occurence ::= ('?' | '*' | '+')? #[derive(Clone, Debug)] pub enum Occurence { Once, Optional, Many0, Many1, } #[derive(Clone, Debug)] pub enum ChildrenKind<'s> { Choice(Choice<'s>), Seq(Seq<'s>), } /// [47] children ::= (choice | seq) ('?' | '*' | '+')? #[derive(Clone, Debug)] pub struct Children<'s> { kind: ChildrenKind<'s>, occurence: Occurence, } #[derive(Clone, Debug)] pub enum CpKind<'s> { Name(QName<'s>), Choice(Choice<'s>), Seq(Seq<'s>), } /// [18] cp ::= (QName | choice | seq) ('?' | '*' | '+')? /// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')? #[derive(Clone, Debug)] pub struct Cp<'s> { kind: CpKind<'s>, occurence: Occurence, } /// [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')' #[derive(Clone, Debug)] pub struct Choice<'s>(Vec>); /// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')' #[derive(Clone, Debug)] pub struct Seq<'s>(Vec>); // always contains #PCDATA /// [19] Mixed ::= '(' S? '#PCDATA' (S? '|' S? QName)* S? ')*' | '(' S? '#PCDATA' S? ')' /// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S? '#PCDATA' S? ')' #[derive(Clone, Debug)] pub struct Mixed<'s>(Vec>); /// [20] AttlistDecl ::= '' /// [52] AttlistDecl ::= '' #[derive(Debug)] pub struct AttlistDecl<'s> { element_type: QName<'s>, att_defs: Vec>, } #[derive(Debug)] pub enum AttDefName<'s> { QName(QName<'s>), NSAttName(NSAttName<'s>), } /// [21] AttDef ::= S (QName | NSAttName) S AttType S DefaultDecl /// [53] AttDef ::= S Name S AttType S DefaultDecl #[derive(Debug)] pub struct AttDef<'s> { name: AttDefName<'s>, att_type: AttType<'s>, default_decl: DefaultDecl<'s>, } /// [54] AttType ::= StringType | TokenizedType | EnumeratedType #[derive(Clone, Debug)] pub enum AttType<'s> { StringType, TokenizedType(TokenizedType), EnumeratedType(EnumeratedType<'s>), } /// [55] StringType ::= 'CDATA' #[derive(Clone)] pub struct StringType; /// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS' #[derive(Clone, Debug)] pub enum TokenizedType { ID, IDRef, IDRefs, Entity, Entities, NMToken, NMTokens, } /// [57] EnumeratedType ::= NotationType | Enumeration #[derive(Debug, Clone)] pub enum EnumeratedType<'s> { NotationType(NotationType<'s>), Enumeration(Enumeration<'s>), } /// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')' #[derive(Debug, Clone)] pub struct NotationType<'s>(Vec>); /// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')' #[derive(Debug, Clone)] pub struct Enumeration<'s>(Vec>); /// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue) #[derive(Debug, Clone)] pub enum DefaultDecl<'s> { Required, Implied, /// if bool == true, attribute MUST always have default value Fixed(bool, AttValue<'s>), } /// [61] conditionalSect ::= includeSect | ignoreSect pub enum ConditionalSect<'s> { IncludeSect(IncludeSect<'s>), IgnoreSect(IgnoreSect<'s>), } /// [62] includeSect ::= '' pub struct IncludeSect<'s>(ExtSubsetDecl<'s>); /// [63] ignoreSect ::= '' pub struct IgnoreSect<'s>(Vec>); /// [64] ignoreSectContents ::= Ignore ('' Ignore)* pub struct IgnoreSectContents<'s> { // TODO: what the fuck does this mean ignore: Ignore<'s>, ignore_list: Vec<(IgnoreSectContents<'s>, Ignore<'s>)>, } /// [65] Ignore ::= Char* - (Char* ('') Char*) pub struct Ignore<'s>(&'s str); /// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';' #[derive(Clone, Debug, PartialEq, Eq)] pub enum CharRef<'s> { Decimal(&'s str), Hexadecimal(&'s str), } impl<'s> CharRef<'s> { pub fn process(&self) -> crate::Result { let int: u32; match self { CharRef::Decimal(dec) => { int = dec .parse() .map_err(|e| Error::InvalidCharRef(CharRefError::ParseInt(e)))?; } CharRef::Hexadecimal(hex) => { int = ::from_str_radix(hex, 16) .map_err(|e| Error::InvalidCharRef(CharRefError::ParseInt(e)))?; } } let c = std::char::from_u32(int); let c = c.ok_or_else(|| Error::InvalidCharRef(CharRefError::IntegerNotAChar(int)))?; if matches!(c, '\u{9}' | '\u{A}' | '\u{D}' | '\u{20}'..='\u{D7FF}' | '\u{E000}'..='\u{FFFD}' | '\u{10000}'..='\u{10FFFF}') { return Ok(c); } else { return Err(Error::InvalidCharRef(CharRefError::InvalidXMLChar(c))); }; } } /// [67] Reference ::= EntityRef | CharRef #[derive(Clone, Debug, PartialEq, Eq)] pub enum Reference<'s> { EntityRef(EntityRef<'s>), CharRef(CharRef<'s>), } impl<'s> Reference<'s> { pub fn process(&self) -> crate::Result { match self { Reference::EntityRef(entity_ref) => match *entity_ref.deref().deref() { "amp" => Ok('&'), "lt" => Ok('<'), "gt" => Ok('>'), "apos" => Ok('\''), "quot" => Ok('"'), e => return Err(Error::EntityProcessError(e.to_string())), }, Reference::CharRef(char_ref) => Ok(char_ref.process()?), } } } /// [68] EntityRef ::= '&' Name ';' #[derive(Clone, Debug, PartialEq, Eq)] pub struct EntityRef<'s>(pub(crate) Name<'s>); impl<'s> Deref for EntityRef<'s> { type Target = Name<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [69] PEReference ::= '%' Name ';' #[derive(Clone, Debug)] #[repr(transparent)] pub struct PEReference<'s>(Name<'s>); /// [70] EntityDecl ::= GEDecl | PEDecl #[derive(Debug)] pub enum EntityDecl<'s> { GEDecl(GEDecl<'s>), PEDecl(PEDecl<'s>), } /// [71] GEDecl ::= '' #[derive(Debug)] pub struct GEDecl<'s> { name: Name<'s>, entity_def: EntityDef<'s>, } /// [72] PEDecl ::= '' #[derive(Debug)] pub struct PEDecl<'s> { name: Name<'s>, pe_def: PEDef<'s>, } /// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?) #[derive(Debug)] pub enum EntityDef<'s> { EntityValue(EntityValue<'s>), ExternalID { external_id: ExternalID<'s>, n_data_decl: Option>, }, } /// [74] PEDef ::= EntityValue | ExternalID #[derive(Debug)] pub enum PEDef<'s> { EntityValue(EntityValue<'s>), ExternalID(ExternalID<'s>), } /// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral #[derive(Debug)] pub enum ExternalID<'s> { SYSTEM { system_identifier: SystemLiteral<'s>, }, PUBLIC { public_identifier: PubidLiteral<'s>, system_identifier: SystemLiteral<'s>, }, } /// [76] NDataDecl ::= S 'NDATA' S Name #[derive(Debug)] pub struct NDataDecl<'s>(Name<'s>); /// [77] TextDecl ::= '' pub struct TextDecl<'s> { version_info: Option, encoding_decl: EncodingDecl<'s>, } /// [78] extParsedEnt ::= TextDecl? content pub struct ExtParsedEnt<'s> { text_decl: Option>, content: Content<'s>, } /// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName "'" ) #[derive(Debug)] // TODO?: select quote version pub struct EncodingDecl<'s>(EncName<'s>); impl<'s> Deref for EncodingDecl<'s> { type Target = EncName<'s>; fn deref(&self) -> &Self::Target { &self.0 } } /// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* #[derive(Debug)] pub struct EncName<'s>(&'s str); impl<'s> Deref for EncName<'s> { type Target = &'s str; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Debug)] pub enum NotationDeclID<'s> { External(ExternalID<'s>), Public(PublicID<'s>), } /// [82] NotationDecl ::= '' #[derive(Debug)] pub struct NotationDecl<'s> { name: Name<'s>, id: NotationDeclID<'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