peanuts/src/writer.rs

142 lines
4.6 KiB
Rust
Raw Normal View History

2024-11-20 15:10:36 +00:00
use std::{collections::HashSet, str::FromStr};
use futures::Sink;
use tokio::io::AsyncWrite;
2024-03-04 16:14:28 +00:00
use crate::{
element::{Element, Name, NamespaceDeclaration},
2024-03-04 16:14:28 +00:00
error::Error,
xml::{self, composers::Composer, parsers_complete::Parser, ETag},
2024-11-20 15:10:36 +00:00
Result,
2024-03-04 16:14:28 +00:00
};
2024-11-01 18:36:11 +00:00
// pub struct Writer<W, C = Composer> {
2024-03-04 16:14:28 +00:00
pub struct Writer<W> {
inner: W,
2024-03-04 16:14:28 +00:00
depth: Vec<Name>,
2024-11-19 16:46:51 +00:00
namespace_declarations: Vec<HashSet<NamespaceDeclaration>>,
2024-03-04 16:14:28 +00:00
}
impl<W: AsyncWrite + Unpin> Writer<W> {
2024-11-20 15:10:36 +00:00
pub async fn write(&mut self, element: Element) -> Result<()> {
todo!()
}
2024-11-20 15:10:36 +00:00
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(())
}
2024-11-20 15:10:36 +00:00
pub async fn write_end(&mut self) -> Result<()> {
2024-11-19 16:46:51 +00:00
if let Some(name) = &self.depth.pop() {
2024-11-20 15:10:36 +00:00
let e_tag;
2024-11-19 16:46:51 +00:00
let namespace_declarations_stack: Vec<_> =
self.namespace_declarations.iter().flatten().collect();
let namespace_declaration = namespace_declarations_stack
.iter()
.rfind(|namespace_declaration| namespace_declaration.namespace == name.namespace)
// will always be in this vector
.unwrap();
let prefix = &namespace_declaration.prefix;
if let Some(prefix) = &prefix {
e_tag = xml::ETag {
name: xml::QName::PrefixedName(xml::PrefixedName {
prefix: xml::Prefix::parse_full(prefix)?,
local_part: xml::LocalPart::parse_full(&name.local_name)?,
}),
};
} else {
e_tag = xml::ETag {
name: xml::QName::UnprefixedName(xml::UnprefixedName::parse_full(
&name.local_name,
)?),
};
}
e_tag.write(&mut self.inner).await?;
self.namespace_declarations.pop();
Ok(())
} else {
return Err(Error::NotInElement("".to_string()));
}
}
2024-03-04 16:14:28 +00:00
}
impl<W: AsyncWrite, E: Into<Element>> Sink<E> for Writer<W> {
type Error = Error;
fn poll_ready(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
2024-11-20 15:10:36 +00:00
) -> std::task::Poll<Result<()>> {
2024-03-04 16:14:28 +00:00
todo!()
}
2024-11-20 15:10:36 +00:00
fn start_send(self: std::pin::Pin<&mut Self>, item: E) -> Result<()> {
2024-03-04 16:14:28 +00:00
todo!()
}
fn poll_flush(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
2024-11-20 15:10:36 +00:00
) -> std::task::Poll<Result<()>> {
2024-03-04 16:14:28 +00:00
todo!()
}
fn poll_close(
self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
2024-11-20 15:10:36 +00:00
) -> std::task::Poll<Result<()>> {
2024-03-04 16:14:28 +00:00
todo!()
}
}