diff options
Diffstat (limited to 'src/writer.rs')
| -rw-r--r-- | src/writer.rs | 72 | 
1 files changed, 62 insertions, 10 deletions
| diff --git a/src/writer.rs b/src/writer.rs index 21d5fe0..9e770c7 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,4 +1,4 @@ -use std::collections::HashSet; +use std::{collections::HashSet, str::FromStr};  use futures::Sink;  use tokio::io::AsyncWrite; @@ -7,6 +7,7 @@ use crate::{      element::{Element, Name, NamespaceDeclaration},      error::Error,      xml::{self, composers::Composer, parsers_complete::Parser, ETag}, +    Result,  };  // pub struct Writer<W, C = Composer> { @@ -17,17 +18,68 @@ pub struct Writer<W> {  }  impl<W: AsyncWrite + Unpin> Writer<W> { -    pub async fn write(&mut self, element: Element) -> Result<(), Error> { +    pub async fn write(&mut self, element: Element) -> Result<()> {          todo!()      } -    pub async fn write_start(&mut self, element: Element) -> Result<(), Error> { -        todo!() +    pub async fn write_start(&mut self, element: Element) -> Result<()> { +        let mut namespace_declarations_stack: Vec<_> = self +            .namespace_declarations +            .iter() +            .flatten() +            .chain(&element.namespace_declarations) +            .collect(); +        let name_namespace_declaration = namespace_declarations_stack +            .iter() +            .rfind(|namespace_declaration| { +                namespace_declaration.namespace == element.name.namespace +            }) +            .ok_or(Error::UndeclaredNamespace(element.name.namespace.clone()))?; +        let prefix = &name_namespace_declaration.prefix; +        let name; +        if let Some(prefix) = &prefix { +            name = xml::QName::PrefixedName(xml::PrefixedName { +                prefix: xml::Prefix::parse_full(prefix)?, +                local_part: xml::LocalPart::parse_full(&element.name.local_name)?, +            }) +        } else { +            name = xml::QName::UnprefixedName(xml::UnprefixedName::parse_full( +                &element.name.local_name, +            )?) +        } + +        namespace_declarations_stack.push(name_namespace_declaration); + +        let mut attributes = Vec::new(); + +        for namespace_declaration in &element.namespace_declarations { +            let ns_name = namespace_declaration +                .prefix +                .as_ref() +                .map(|prefix| -> Result<_> { +                    Ok(xml::NSAttName::PrefixedAttName( +                        xml::PrefixedAttName::parse_full(&prefix)?, +                    )) +                }) +                .unwrap_or(Ok(xml::NSAttName::DefaultAttName))?; +            let value = xml::AttValue::from(namespace_declaration.namespace.as_str()); +            let xml_attribute = xml::Attribute::NamespaceDeclaration { ns_name, value }; +            attributes.push(xml_attribute); +        } + +        let s_tag = xml::STag { name, attributes }; + +        s_tag.write(&mut self.inner).await?; + +        self.depth.push(element.name); +        self.namespace_declarations +            .push(element.namespace_declarations); +        Ok(())      } -    pub async fn write_end(&mut self) -> Result<(), Error> { -        let e_tag; +    pub async fn write_end(&mut self) -> Result<()> {          if let Some(name) = &self.depth.pop() { +            let e_tag;              let namespace_declarations_stack: Vec<_> =                  self.namespace_declarations.iter().flatten().collect();              let namespace_declaration = namespace_declarations_stack @@ -65,25 +117,25 @@ impl<W: AsyncWrite, E: Into<Element>> Sink<E> for Writer<W> {      fn poll_ready(          self: std::pin::Pin<&mut Self>,          cx: &mut std::task::Context<'_>, -    ) -> std::task::Poll<Result<(), Self::Error>> { +    ) -> std::task::Poll<Result<()>> {          todo!()      } -    fn start_send(self: std::pin::Pin<&mut Self>, item: E) -> Result<(), Self::Error> { +    fn start_send(self: std::pin::Pin<&mut Self>, item: E) -> Result<()> {          todo!()      }      fn poll_flush(          self: std::pin::Pin<&mut Self>,          cx: &mut std::task::Context<'_>, -    ) -> std::task::Poll<Result<(), Self::Error>> { +    ) -> std::task::Poll<Result<()>> {          todo!()      }      fn poll_close(          self: std::pin::Pin<&mut Self>,          cx: &mut std::task::Context<'_>, -    ) -> std::task::Poll<Result<(), Self::Error>> { +    ) -> std::task::Poll<Result<()>> {          todo!()      }  } | 
