use std::io;
use tokio::io::{AsyncWrite, AsyncWriteExt};
use super::{
AttDef, AttDefName, AttType, AttValue, AttValueData, AttlistDecl, Attribute, CDEnd, CDSect,
CDStart, CData, Char, CharData, CharRef, Children, ChildrenKind, Choice, Comment,
ConditionalSect, Content, ContentItem, Contentspec, Cp, CpKind, DeclSep, DefaultAttName,
DefaultDecl, DoctypeDecl, Document, ETag, Element, Elementdecl, EmptyElemTag, EncName,
EncodingDecl, EntityDecl, EntityDef, EntityRef, EntityValue, EntityValueData, EnumeratedType,
Enumeration, Eq, ExtParsedEnt, ExtSubset, ExtSubsetDecl, ExtSubsetDeclaration, ExternalID,
GEDecl, Ignore, IgnoreSect, IgnoreSectContents, IncludeSect, IntSubset, LocalPart, MarkupDecl,
Misc, Mixed, NCName, NDataDecl, NSAttName, Name, NameChar, NameStartChar, Names, Nmtoken,
Nmtokens, NotationDecl, NotationDeclID, NotationType, Occurence, PEDecl, PEDef, PEReference,
PITarget, Prefix, PrefixedAttName, PrefixedName, Prolog, PubidChar, PubidLiteral, PublicID,
QName, Reference, SDDecl, STag, Seq, StringType, SystemLiteral, TextDecl, TokenizedType,
UnprefixedName, VersionInfo, VersionNum, XMLDecl, PI, S,
};
/// Compact Composer trait, can create different trait later for pretty composition
pub trait Composer<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite;
}
// namespaces in xml
/// [1] NSAttName ::= PrefixedAttName | DefaultAttName
impl<'s> Composer<'s> for NSAttName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
match self {
NSAttName::PrefixedAttName(prefixed_att_name) => {
prefixed_att_name.write(writer).await?
}
NSAttName::DefaultAttName => DefaultAttName.write(writer).await?,
}
Ok(())
}
}
/// [2] PrefixedAttName ::= 'xmlns:' NCName
impl<'s> Composer<'s> for PrefixedAttName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
writer.write_all("xmlns:".as_bytes()).await?;
self.0.write(writer).await?;
Ok(())
}
}
/// [3] DefaultAttName ::= 'xmlns';
impl Composer<'_> for DefaultAttName {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
writer.write_all("xmlns".as_bytes()).await?;
Ok(())
}
}
/// [4] NCName ::= Name - (Char* ':' Char*)
impl<'s> Composer<'s> for NCName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [7] QName ::= PrefixedName | UnprefixedName
impl<'s> Composer<'s> for QName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
match self {
QName::PrefixedName(prefixed_name) => prefixed_name.write(writer).await?,
QName::UnprefixedName(unprefixed_name) => unprefixed_name.write(writer).await?,
}
Ok(())
}
}
/// [8] PrefixedName ::= Prefix ':' LocalPart
impl<'s> Composer<'s> for PrefixedName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: AsyncWrite + Unpin,
{
self.prefix.write(writer).await?;
writer.write_all(":".as_bytes()).await?;
self.local_part.write(writer).await?;
Ok(())
}
}
/// [9] UnprefixedName ::= LocalPart
impl<'s> Composer<'s> for UnprefixedName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.0.write(writer).await?;
Ok(())
}
}
/// [10] Prefix ::= NCName
impl<'s> Composer<'s> for Prefix<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.0.write(writer).await?;
Ok(())
}
}
/// [11] LocalPart ::= NCName
impl<'s> Composer<'s> for LocalPart<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.0.write(writer).await?;
Ok(())
}
}
// xml spec
/// [1] document ::= prolog element Misc*
impl<'s> Composer<'s> for Document<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.0.write(writer).await?;
self.1.write(writer).await?;
for misc in &self.2 {
misc.write(writer).await?
}
Ok(())
}
}
/// [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] /* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
impl Composer<'_> for Char {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.to_string().as_bytes()).await?;
Ok(())
}
}
/// [3] S ::= (#x20 | #x9 | #xD | #xA)+
impl<'s> Composer<'s> for S {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("\u{20}".as_bytes()).await?;
Ok(())
}
}
/// [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]
impl Composer<'_> for NameStartChar {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.to_string().as_bytes()).await?;
Ok(())
}
}
/// [4a] NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
impl Composer<'_> for NameChar {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.to_string().as_bytes()).await?;
Ok(())
}
}
/// [5] Name ::= NameStartChar (NameChar)*
impl<'s> Composer<'s> for Name<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [6] Names ::= Name (#x20 Name)*
impl<'s> Composer<'s> for Names<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
let mut first = true;
for name in &self.0 {
if !first {
writer.write_all("\u{20}".as_bytes()).await?;
}
name.write(writer).await?;
if first {
first = false
}
}
Ok(())
}
}
/// [7] Nmtoken ::= (NameChar)+
impl<'s> Composer<'s> for Nmtoken<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [8] Nmtokens ::= Nmtoken (#x20 Nmtoken)*
impl<'s> Composer<'s> for Nmtokens<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
let mut first = true;
for nmtoken in &self.0 {
if !first {
writer.write_all("\u{20}".as_bytes()).await?;
}
nmtoken.write(writer).await?;
if first {
first = false
}
}
Ok(())
}
}
/// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
/// | "'" ([^%&'] | PEReference | Reference)* "'"
impl<'s> Composer<'s> for EntityValue<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
EntityValue::DoubleQuoted(entity_value_data) => {
writer.write_all("\"".as_bytes()).await?;
for entity_value_data in entity_value_data {
match entity_value_data {
EntityValueData::String(s) => writer.write_all(s.as_bytes()).await?,
EntityValueData::PEReference(pe_reference) => {
pe_reference.write(writer).await?
}
EntityValueData::Reference(reference) => reference.write(writer).await?,
}
}
writer.write_all("\"".as_bytes()).await?;
}
EntityValue::SingleQuoted(entity_value_data) => {
writer.write_all("'".as_bytes()).await?;
for entity_value_data in entity_value_data {
match entity_value_data {
EntityValueData::String(s) => writer.write_all(s.as_bytes()).await?,
EntityValueData::PEReference(pe_reference) => {
pe_reference.write(writer).await?
}
EntityValueData::Reference(reference) => reference.write(writer).await?,
}
}
writer.write_all("'".as_bytes()).await?;
}
}
Ok(())
}
}
/// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
/// | "'" ([^<&'] | Reference)* "'"
impl<'s> Composer<'s> for AttValue<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
AttValue::DoubleQuoted(att_value_data) => {
writer.write_all("\"".as_bytes()).await?;
for att_value_data in att_value_data {
match att_value_data {
AttValueData::String(s) => writer.write_all(s.as_bytes()).await?,
AttValueData::Reference(reference) => reference.write(writer).await?,
}
}
writer.write_all("\"".as_bytes()).await?;
}
AttValue::SingleQuoted(att_value_data) => {
writer.write_all("'".as_bytes()).await?;
for att_value_data in att_value_data {
match att_value_data {
AttValueData::String(s) => writer.write_all(s.as_bytes()).await?,
AttValueData::Reference(reference) => reference.write(writer).await?,
}
}
writer.write_all("'".as_bytes()).await?;
}
}
Ok(())
}
}
/// [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'")
impl<'s> Composer<'s> for SystemLiteral<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
SystemLiteral::DoubleQuoted(s) => {
writer.write_all("\"".as_bytes()).await?;
writer.write_all(s.as_bytes()).await?;
writer.write_all("\"".as_bytes()).await?;
}
SystemLiteral::SingleQuoted(s) => {
writer.write_all("'".as_bytes()).await?;
writer.write_all(s.as_bytes()).await?;
writer.write_all("'".as_bytes()).await?;
}
}
Ok(())
}
}
/// [12] PubidLiteral ::= '"' PubidChar* '"' | "'" (PubidChar - "'")* "'"
impl<'s> Composer<'s> for PubidLiteral<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
PubidLiteral::DoubleQuoted(s) => {
writer.write_all("\"".as_bytes()).await?;
writer.write_all(s.as_bytes()).await?;
writer.write_all("\"".as_bytes()).await?;
}
PubidLiteral::SingleQuoted(s) => {
writer.write_all("'".as_bytes()).await?;
writer.write_all(s.as_bytes()).await?;
writer.write_all("'".as_bytes()).await?;
}
}
Ok(())
}
}
/// [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
impl Composer<'_> for PubidChar {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.to_string().as_bytes()).await?;
Ok(())
}
}
/// [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
impl<'s> Composer<'s> for CharData<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [15] Comment ::= '<!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
impl<'s> Composer<'s> for Comment<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!--".as_bytes()).await?;
writer.write_all(self.0.as_bytes()).await?;
writer.write_all("-->".as_bytes()).await?;
Ok(())
}
}
/// [16] PI ::= '<?' PITarget (S (Char* - (Char* '?>' Char*)))? '?>'
impl<'s> Composer<'s> for PI<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<?".as_bytes()).await?;
self.target.write(writer).await?;
if let Some(instruction) = self.instruction {
S.write(writer).await?;
writer.write_all(instruction.as_bytes()).await?;
}
writer.write_all("?>".as_bytes()).await?;
Ok(())
}
}
/// [17] PITarget ::= Name - (('X' | 'x') ('M' | 'm') ('L' | 'l'))
impl<'s> Composer<'s> for PITarget<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.0.write(writer).await?;
Ok(())
}
}
/// [18] CDSect ::= CDStart CData CDEnd
impl<'s> Composer<'s> for CDSect<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
CDStart.write(writer).await?;
self.0.write(writer).await?;
CDEnd.write(writer).await?;
Ok(())
}
}
/// [19] CDStart ::= '<![CDATA['
impl Composer<'_> for CDStart {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<![CDATA[".as_bytes()).await?;
Ok(())
}
}
/// [20] CData ::= (Char* - (Char* ']]>' Char*))
impl<'s> Composer<'s> for CData<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [21] CDEnd ::= ']]>'
impl Composer<'_> for CDEnd {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("]]>".as_bytes()).await?;
Ok(())
}
}
/// [22] prolog ::= XMLDecl? Misc* (doctypedecl Misc*)?
impl<'s> Composer<'s> for Prolog<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
if let Some(xml_decl) = &self.0 {
xml_decl.write(writer).await?;
}
for misc in &self.1 {
misc.write(writer).await?;
}
if let Some((doctype_decl, miscs)) = &self.2 {
doctype_decl.write(writer).await?;
for misc in miscs {
misc.write(writer).await?;
}
}
Ok(())
}
}
/// [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
impl<'s> Composer<'s> for XMLDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<?xml".as_bytes()).await?;
self.version_info.write(writer).await?;
if let Some(encoding_decl) = &self.encoding_decl {
encoding_decl.write(writer).await?
}
if let Some(sd_decl) = &self.sd_decl {
sd_decl.write(writer).await?
}
writer.write_all("?>".as_bytes()).await?;
Ok(())
}
}
/// [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
impl Composer<'_> for VersionInfo {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
S.write(writer).await?;
writer.write_all("version".as_bytes()).await?;
Eq.write(writer).await?;
match self {
VersionInfo::SingleQuoted(version_num) => {
writer.write_all("'".as_bytes()).await?;
version_num.write(writer).await?;
writer.write_all("'".as_bytes()).await?;
}
VersionInfo::DoubleQuoted(version_num) => {
writer.write_all("\"".as_bytes()).await?;
version_num.write(writer).await?;
writer.write_all("\"".as_bytes()).await?;
}
}
Ok(())
}
}
/// [25] Eq ::= S? '=' S?
impl Composer<'_> for Eq {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("=".as_bytes()).await?;
Ok(())
}
}
/// [26] VersionNum ::= '1.' [0-9]+
impl Composer<'_> for VersionNum {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
VersionNum::One => writer.write_all("1.0".as_bytes()).await?,
VersionNum::OneDotOne => writer.write_all("1.1".as_bytes()).await?,
}
Ok(())
}
}
/// [27] Misc ::= Comment | PI | S
impl<'s> Composer<'s> for Misc<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Misc::Comment(comment) => comment.write(writer).await?,
Misc::PI(pi) => pi.write(writer).await?,
Misc::S => {}
}
Ok(())
}
}
/// [16] doctypedecl ::= '<!DOCTYPE' S QName (S ExternalID)? S? ('[' (markupdecl | PEReference | S)* ']' S?)? '>'
/// [28] doctypedecl ::= '<!DOCTYPE' S Name (S ExternalID)? S? ('[' intSubset ']' S?)? '>'
impl<'s> Composer<'s> for DoctypeDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!DOCTYPE".as_bytes()).await?;
S.write(writer).await?;
self.name.write(writer).await?;
if let Some(external_id) = &self.external_id {
S.write(writer).await?;
external_id.write(writer).await?;
}
if let Some(int_subset) = &self.int_subset {
writer.write_all("[".as_bytes()).await?;
int_subset.write(writer).await?;
writer.write_all("]".as_bytes()).await?;
}
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [28a] DeclSep ::= PEReference | S
impl<'s> Composer<'s> for DeclSep<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
DeclSep::PEReference(pe_reference) => pe_reference.write(writer).await?,
DeclSep::S => S.write(writer).await?,
}
Ok(())
}
}
/// [28b] intSubset ::= (markupdecl | DeclSep)*
impl<'s> Composer<'s> for IntSubset<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
for declaration in self {
match declaration {
super::IntSubsetDeclaration::MarkupDecl(markup_decl) => {
markup_decl.write(writer).await?
}
super::IntSubsetDeclaration::DeclSep(decl_sep) => decl_sep.write(writer).await?,
}
}
Ok(())
}
}
/// [29] markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment
impl<'s> Composer<'s> for MarkupDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
MarkupDecl::Elementdecl(elementdecl) => elementdecl.write(writer).await?,
MarkupDecl::AttlistDecl(attlist_decl) => attlist_decl.write(writer).await?,
MarkupDecl::EntityDecl(entity_decl) => entity_decl.write(writer).await?,
MarkupDecl::NotationDecl(notation_decl) => notation_decl.write(writer).await?,
MarkupDecl::PI(pi) => pi.write(writer).await?,
MarkupDecl::Comment(comment) => comment.write(writer).await?,
}
Ok(())
}
}
/// [30] extSubset ::= TextDecl? extSubsetDecl
impl<'s> Composer<'s> for ExtSubset<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
if let Some(text_decl) = &self.text_decl {
text_decl.write(writer).await?
}
self.ext_subset_decl.write(writer).await?;
Ok(())
}
}
/// [31] extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)*
impl<'s> Composer<'s> for ExtSubsetDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
for declaration in self {
match declaration {
ExtSubsetDeclaration::MarkupDecl(markup_decl) => markup_decl.write(writer).await?,
ExtSubsetDeclaration::ConditionalSect(conditional_sect) => {
Box::pin(conditional_sect.write(writer)).await?
}
ExtSubsetDeclaration::DeclSep(decl_sep) => decl_sep.write(writer).await?,
}
}
Ok(())
}
}
/// [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'") | ('"' ('yes' | 'no') '"'))
impl Composer<'_> for SDDecl {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
S.write(writer).await?;
writer.write_all("standalone".as_bytes()).await?;
Eq.write(writer).await?;
match self {
SDDecl::SingleQuoted(sd_decl) => {
writer.write_all("'".as_bytes()).await?;
match sd_decl {
true => writer.write_all("yes".as_bytes()).await?,
false => writer.write_all("no".as_bytes()).await?,
}
writer.write_all("'".as_bytes()).await?;
}
SDDecl::DoubleQuoted(sd_decl) => {
writer.write_all("\"".as_bytes()).await?;
match sd_decl {
true => writer.write_all("yes".as_bytes()).await?,
false => writer.write_all("no".as_bytes()).await?,
}
writer.write_all("\"".as_bytes()).await?;
}
}
Ok(())
}
}
// (Productions 33 through 38 have been removed.)
/// [39] element ::= EmptyElemTag | STag content ETag
impl<'s> Composer<'s> for Element<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Element::Empty(empty_elem_tag) => empty_elem_tag.write(writer).await?,
Element::NotEmpty(s_tag, content, e_tag) => {
s_tag.write(writer).await?;
content.write(writer).await?;
e_tag.write(writer).await?;
}
}
Ok(())
}
}
/// [12] STag ::= '<' QName (S Attribute)* S? '>'
/// [40] STag ::= '<' Name (S Attribute)* S? '>'
impl<'s> Composer<'s> for STag<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<".as_bytes()).await?;
self.name.write(writer).await?;
for attribute in &self.attributes {
S.write(writer).await?;
attribute.write(writer).await?;
}
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [15] Attribute ::= NSAttName Eq AttValue | QName Eq AttValue
impl<'s> Composer<'s> for Attribute<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Attribute::NamespaceDeclaration { ns_name, value } => {
ns_name.write(writer).await?;
Eq.write(writer).await?;
value.write(writer).await?;
}
Attribute::Attribute { name, value } => {
name.write(writer).await?;
Eq.write(writer).await?;
value.write(writer).await?;
}
}
Ok(())
}
}
/// [13] ETag ::= '</' QName S? '>'
impl<'s> Composer<'s> for ETag<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("</".as_bytes()).await?;
self.name.write(writer).await?;
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [43] content ::= CharData? ((element | Reference | CDSect | PI | Comment) CharData?)*
impl<'s> Composer<'s> for Content<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
if let Some(char_data) = &self.char_data {
char_data.write(writer).await?;
}
for (content, char_data) in &self.content {
match content {
ContentItem::Element(element) => Box::pin(element.write(writer)).await?,
ContentItem::Reference(reference) => reference.write(writer).await?,
ContentItem::CDSect(cd_sect) => cd_sect.write(writer).await?,
ContentItem::PI(pi) => pi.write(writer).await?,
ContentItem::Comment(comment) => comment.write(writer).await?,
_ => todo!("verify no split chardata"),
}
if let Some(char_data) = char_data {
char_data.write(writer).await?;
}
}
Ok(())
}
}
/// [14] EmptyElemTag ::= '<' QName (S Attribute)* S? '/>'
impl<'s> Composer<'s> for EmptyElemTag<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<".as_bytes()).await?;
self.name.write(writer).await?;
for attribute in &self.attributes {
S.write(writer).await?;
attribute.write(writer).await?;
}
writer.write_all("/>".as_bytes()).await?;
Ok(())
}
}
/// [17] elementdecl ::= '<!ELEMENT' S QName S contentspec S? '>'
impl<'s> Composer<'s> for Elementdecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!ELEMENT".as_bytes()).await?;
S.write(writer).await?;
self.name.write(writer).await?;
S.write(writer).await?;
self.contentspec.write(writer).await?;
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
impl<'s> Composer<'s> for Contentspec<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Contentspec::Empty => writer.write_all("EMPTY".as_bytes()).await?,
Contentspec::Any => writer.write_all("ANY".as_bytes()).await?,
Contentspec::Mixed(mixed) => mixed.write(writer).await?,
Contentspec::Children(children) => children.write(writer).await?,
}
Ok(())
}
}
/// Occurence ::= ('?' | '*' | '+')?
impl Composer<'_> for Occurence {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Occurence::Once => {}
Occurence::Optional => writer.write_all("?".as_bytes()).await?,
Occurence::Many0 => writer.write_all("*".as_bytes()).await?,
Occurence::Many1 => writer.write_all("+".as_bytes()).await?,
}
Ok(())
}
}
/// [47] children ::= (choice | seq) ('?' | '*' | '+')?
impl<'s> Composer<'s> for Children<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match &self.kind {
ChildrenKind::Choice(choice) => choice.write(writer).await?,
ChildrenKind::Seq(seq) => seq.write(writer).await?,
}
self.occurence.write(writer).await?;
Ok(())
}
}
/// [18] cp ::= (QName | choice | seq) ('?' | '*' | '+')?
impl<'s> Composer<'s> for Cp<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match &self.kind {
CpKind::Name(q_name) => q_name.write(writer).await?,
CpKind::Choice(choice) => Box::pin(choice.write(writer)).await?,
CpKind::Seq(seq) => Box::pin(seq.write(writer)).await?,
}
self.occurence.write(writer).await?;
Ok(())
}
}
/// [49] choice ::= '(' S? cp ( S? '|' S? cp )+ S? ')'
impl<'s> Composer<'s> for Choice<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("(".as_bytes()).await?;
let mut first = true;
for cp in &self.0 {
if !first {
writer.write_all("|".as_bytes()).await?;
}
cp.write(writer).await?;
if first {
first = false
}
}
writer.write_all(")".as_bytes()).await?;
Ok(())
}
}
/// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
impl<'s> Composer<'s> for Seq<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("(".as_bytes()).await?;
let mut first = true;
for cp in &self.0 {
if !first {
writer.write_all(",".as_bytes()).await?;
}
cp.write(writer).await?;
if first {
first = false
}
}
writer.write_all(")".as_bytes()).await?;
Ok(())
}
}
/// [19] Mixed ::= '(' S? '#PCDATA' (S? '|' S? QName)* S? ')*' | '(' S? '#PCDATA' S? ')'
impl<'s> Composer<'s> for Mixed<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("(#PCDATA".as_bytes()).await?;
if !self.0.is_empty() {
for q_name in &self.0 {
writer.write_all("|".as_bytes()).await?;
q_name.write(writer).await?;
}
writer.write_all(")*".as_bytes()).await?;
} else {
writer.write_all(")".as_bytes()).await?;
}
Ok(())
}
}
/// [20] AttlistDecl ::= '<!ATTLIST' S QName AttDef* S? '>'
impl<'s> Composer<'s> for AttlistDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!ATTLIST".as_bytes()).await?;
S.write(writer).await?;
self.element_type.write(writer).await?;
for att_def in &self.att_defs {
att_def.write(writer).await?;
}
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [21] AttDef ::= S (QName | NSAttName) S AttType S DefaultDecl
impl<'s> Composer<'s> for AttDef<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
S.write(writer).await?;
match &self.name {
AttDefName::QName(q_name) => q_name.write(writer).await?,
AttDefName::NSAttName(ns_att_name) => ns_att_name.write(writer).await?,
}
S.write(writer).await?;
self.att_type.write(writer).await?;
S.write(writer).await?;
self.default_decl.write(writer).await?;
Ok(())
}
}
/// [54] AttType ::= StringType | TokenizedType | EnumeratedType
impl<'s> Composer<'s> for AttType<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
AttType::StringType => StringType.write(writer).await?,
AttType::TokenizedType(tokenized_type) => tokenized_type.write(writer).await?,
AttType::EnumeratedType(enumerated_type) => enumerated_type.write(writer).await?,
}
Ok(())
}
}
/// [55] StringType ::= 'CDATA'
impl Composer<'_> for StringType {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("CDATA".as_bytes()).await?;
Ok(())
}
}
/// [56] TokenizedType ::= 'ID' | 'IDREF' | 'IDREFS' | 'ENTITY' | 'ENTITIES' | 'NMTOKEN' | 'NMTOKENS'
impl Composer<'_> for TokenizedType {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
TokenizedType::ID => writer.write_all("ID".as_bytes()).await?,
TokenizedType::IDRef => writer.write_all("IDREF".as_bytes()).await?,
TokenizedType::IDRefs => writer.write_all("IDREFS".as_bytes()).await?,
TokenizedType::Entity => writer.write_all("ENTITY".as_bytes()).await?,
TokenizedType::Entities => writer.write_all("ENTITIES".as_bytes()).await?,
TokenizedType::NMToken => writer.write_all("NMTOKEN".as_bytes()).await?,
TokenizedType::NMTokens => writer.write_all("NMTOKENS".as_bytes()).await?,
}
Ok(())
}
}
/// [57] EnumeratedType ::= NotationType | Enumeration
impl<'s> Composer<'s> for EnumeratedType<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
EnumeratedType::NotationType(notation_type) => notation_type.write(writer).await?,
EnumeratedType::Enumeration(enumeration) => enumeration.write(writer).await?,
}
Ok(())
}
}
/// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
impl<'s> Composer<'s> for NotationType<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("NOTATION".as_bytes()).await?;
S.write(writer).await?;
writer.write_all("(".as_bytes()).await?;
let mut first = true;
for name in &self.0 {
if !first {
writer.write_all("|".as_bytes()).await?;
}
name.write(writer).await?;
if first {
first = false
}
}
writer.write_all(")".as_bytes()).await?;
Ok(())
}
}
/// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
impl<'s> Composer<'s> for Enumeration<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("(".as_bytes()).await?;
let mut first = true;
for nm_token in &self.0 {
if !first {
writer.write_all("|".as_bytes()).await?;
}
nm_token.write(writer).await?;
if first {
first = false
}
}
writer.write_all(")".as_bytes()).await?;
Ok(())
}
}
/// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
impl<'s> Composer<'s> for DefaultDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
DefaultDecl::Required => writer.write_all("#REQUIRED".as_bytes()).await?,
DefaultDecl::Implied => writer.write_all("#IMPLIED".as_bytes()).await?,
DefaultDecl::Fixed(fixed, att_value) => {
if *fixed {
writer.write_all("#FIXED".as_bytes()).await?;
S.write(writer).await?;
}
att_value.write(writer).await?
}
}
Ok(())
}
}
/// [61] conditionalSect ::= includeSect | ignoreSect
impl<'s> Composer<'s> for ConditionalSect<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
ConditionalSect::IncludeSect(include_sect) => include_sect.write(writer).await?,
ConditionalSect::IgnoreSect(ignore_sect) => ignore_sect.write(writer).await?,
}
Ok(())
}
}
/// [62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
impl<'s> Composer<'s> for IncludeSect<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<![INCLUDE[".as_bytes()).await?;
self.0.write(writer).await?;
writer.write_all("]]>".as_bytes()).await?;
Ok(())
}
}
/// [63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
impl<'s> Composer<'s> for IgnoreSect<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<![IGNORE[".as_bytes()).await?;
for ignore_sect_contents in &self.0 {
ignore_sect_contents.write(writer).await?;
}
writer.write_all("]]>".as_bytes()).await?;
Ok(())
}
}
/// [64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
impl<'s> Composer<'s> for IgnoreSectContents<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
self.ignore.write(writer).await?;
for (ignore_sect_contents, ignore) in &self.ignore_list {
writer.write_all("<![".as_bytes()).await?;
Box::pin(ignore_sect_contents.write(writer)).await?;
writer.write_all("]]>".as_bytes()).await?;
ignore.write(writer).await?;
}
Ok(())
}
}
/// [65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
impl<'s> Composer<'s> for Ignore<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
impl<'s> Composer<'s> for CharRef<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
CharRef::Decimal(decimal) => {
writer.write_all("&#".as_bytes()).await?;
writer.write_all(decimal.as_bytes()).await?;
writer.write_all(";".as_bytes()).await?;
}
CharRef::Hexadecimal(hexadecimal) => {
writer.write_all("&#x".as_bytes()).await?;
writer.write_all(hexadecimal.as_bytes()).await?;
writer.write_all(";".as_bytes()).await?;
}
}
Ok(())
}
}
/// [67] Reference ::= EntityRef | CharRef
impl<'s> Composer<'s> for Reference<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
Reference::EntityRef(entity_ref) => entity_ref.write(writer).await?,
Reference::CharRef(char_ref) => char_ref.write(writer).await?,
}
Ok(())
}
}
/// [68] EntityRef ::= '&' Name ';'
impl<'s> Composer<'s> for EntityRef<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("&".as_bytes()).await?;
self.0.write(writer).await?;
writer.write_all(";".as_bytes()).await?;
Ok(())
}
}
/// [69] PEReference ::= '%' Name ';'
impl<'s> Composer<'s> for PEReference<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("%".as_bytes()).await?;
self.0.write(writer).await?;
writer.write_all(";".as_bytes()).await?;
Ok(())
}
}
/// [70] EntityDecl ::= GEDecl | PEDecl
impl<'s> Composer<'s> for EntityDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
EntityDecl::GEDecl(ge_decl) => ge_decl.write(writer).await?,
EntityDecl::PEDecl(pe_decl) => pe_decl.write(writer).await?,
}
Ok(())
}
}
/// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
impl<'s> Composer<'s> for GEDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!ENTITY".as_bytes()).await?;
S.write(writer).await?;
self.name.write(writer).await?;
S.write(writer).await?;
self.entity_def.write(writer).await?;
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
impl<'s> Composer<'s> for PEDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!ENTITY".as_bytes()).await?;
S.write(writer).await?;
writer.write_all("%".as_bytes()).await?;
S.write(writer).await?;
self.name.write(writer).await?;
S.write(writer).await?;
self.pe_def.write(writer).await?;
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
impl<'s> Composer<'s> for EntityDef<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
EntityDef::EntityValue(entity_value) => entity_value.write(writer).await?,
EntityDef::ExternalID {
external_id,
n_data_decl,
} => {
external_id.write(writer).await?;
if let Some(n_data_decl) = n_data_decl {
n_data_decl.write(writer).await?;
}
}
}
Ok(())
}
}
/// [74] PEDef ::= EntityValue | ExternalID
impl<'s> Composer<'s> for PEDef<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
PEDef::EntityValue(entity_value) => entity_value.write(writer).await?,
PEDef::ExternalID(external_id) => external_id.write(writer).await?,
}
Ok(())
}
}
/// [75] ExternalID ::= 'SYSTEM' S SystemLiteral | 'PUBLIC' S PubidLiteral S SystemLiteral
impl<'s> Composer<'s> for ExternalID<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
match self {
ExternalID::SYSTEM { system_identifier } => {
writer.write_all("SYSTEM".as_bytes()).await?;
S.write(writer).await?;
system_identifier.write(writer).await?;
}
ExternalID::PUBLIC {
public_identifier,
system_identifier,
} => {
writer.write_all("PUBLIC".as_bytes()).await?;
S.write(writer).await?;
public_identifier.write(writer).await?;
S.write(writer).await?;
system_identifier.write(writer).await?;
}
}
Ok(())
}
}
/// [76] NDataDecl ::= S 'NDATA' S Name
impl<'s> Composer<'s> for NDataDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
S.write(writer).await?;
writer.write_all("NDATA".as_bytes()).await?;
S.write(writer).await?;
self.0.write(writer).await?;
Ok(())
}
}
/// [77] TextDecl ::= '<?xml' VersionInfo? EncodingDecl S? '?>'
impl<'s> Composer<'s> for TextDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<?xml".as_bytes()).await?;
if let Some(version_info) = &self.version_info {
version_info.write(writer).await?;
}
self.encoding_decl.write(writer).await?;
writer.write_all("?>".as_bytes()).await?;
Ok(())
}
}
/// [78] extParsedEnt ::= TextDecl? content
impl<'s> Composer<'s> for ExtParsedEnt<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
if let Some(text_decl) = &self.text_decl {
text_decl.write(writer).await?;
}
self.content.write(writer).await?;
Ok(())
}
}
/// [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' | "'" EncName
impl<'s> Composer<'s> for EncodingDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
S.write(writer).await?;
writer.write_all("encoding".as_bytes()).await?;
Eq.write(writer).await?;
writer.write_all("\"".as_bytes()).await?;
self.0.write(writer).await?;
writer.write_all("\"".as_bytes()).await?;
Ok(())
}
}
/// [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
impl<'s> Composer<'s> for EncName<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all(self.0.as_bytes()).await?;
Ok(())
}
}
/// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S? '>'
impl<'s> Composer<'s> for NotationDecl<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("<!NOTATION".as_bytes()).await?;
S.write(writer).await?;
self.name.write(writer).await?;
S.write(writer).await?;
match &self.id {
NotationDeclID::External(external_id) => external_id.write(writer).await?,
NotationDeclID::Public(public_id) => public_id.write(writer).await?,
}
writer.write_all(">".as_bytes()).await?;
Ok(())
}
}
/// [83] PublicID ::= 'PUBLIC' S PubidLiteral
impl<'s> Composer<'s> for PublicID<'s> {
async fn write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Unpin + AsyncWrite,
{
writer.write_all("PUBLIC".as_bytes()).await?;
S.write(writer).await?;
self.0.write(writer).await?;
Ok(())
}
}