summaryrefslogtreecommitdiffstats
path: root/src/element.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/element.rs')
-rw-r--r--src/element.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/element.rs b/src/element.rs
new file mode 100644
index 0000000..21b1a3e
--- /dev/null
+++ b/src/element.rs
@@ -0,0 +1,108 @@
+use async_recursion::async_recursion;
+use quick_xml::events::Event;
+use quick_xml::{Reader, Writer};
+use tokio::io::{AsyncBufRead, AsyncWrite};
+
+use crate::Result;
+
+#[derive(Debug)]
+pub struct Element<'e> {
+ pub event: Event<'e>,
+ pub content: Option<Vec<Element<'e>>>,
+}
+
+// TODO: make method
+#[async_recursion]
+pub async fn write<'e: 'async_recursion, W: AsyncWrite + Unpin + Send>(
+ element: Element<'e>,
+ writer: &mut Writer<W>,
+) -> Result<()> {
+ match element.event {
+ Event::Start(e) => {
+ writer.write_event_async(Event::Start(e.clone())).await?;
+ if let Some(content) = element.content {
+ for e in content {
+ write(e, writer).await?;
+ }
+ }
+ writer.write_event_async(Event::End(e.to_end())).await?;
+ return Ok(());
+ }
+ e => Ok(writer.write_event_async(e).await?),
+ }
+}
+
+impl<'e> Element<'e> {
+ pub async fn write_start<W: AsyncWrite + Unpin + Send>(
+ &self,
+ writer: &mut Writer<W>,
+ ) -> Result<()> {
+ match self.event.as_ref() {
+ Event::Start(e) => Ok(writer.write_event_async(Event::Start(e.clone())).await?),
+ e => Err(ElementError::NotAStart(e.clone().into_owned()).into()),
+ }
+ }
+
+ pub async fn write_end<W: AsyncWrite + Unpin + Send>(
+ &self,
+ writer: &mut Writer<W>,
+ ) -> Result<()> {
+ match self.event.as_ref() {
+ Event::Start(e) => Ok(writer
+ .write_event_async(Event::End(e.clone().to_end()))
+ .await?),
+ e => Err(ElementError::NotAStart(e.clone().into_owned()).into()),
+ }
+ }
+
+ #[async_recursion]
+ pub async fn read<R: AsyncBufRead + Unpin + Send>(
+ reader: &mut Reader<R>,
+ ) -> Result<Option<Self>> {
+ let mut buf = Vec::new();
+ let event = reader.read_event_into_async(&mut buf).await?;
+ match event {
+ Event::Start(e) => {
+ let mut content_vec = Vec::new();
+ while let Some(sub_element) = Element::read(reader).await? {
+ content_vec.push(sub_element)
+ }
+ let mut content = None;
+ if !content_vec.is_empty() {
+ content = Some(content_vec)
+ }
+ Ok(Some(Self {
+ event: Event::Start(e.into_owned()),
+ content,
+ }))
+ }
+ Event::End(_) => Ok(None),
+ e => Ok(Some(Self {
+ event: e.into_owned(),
+ content: None,
+ })),
+ }
+ }
+
+ #[async_recursion]
+ pub async fn read_start<R: AsyncBufRead + Unpin + Send>(
+ reader: &mut Reader<R>,
+ ) -> Result<Self> {
+ let mut buf = Vec::new();
+ let event = reader.read_event_into_async(&mut buf).await?;
+ match event {
+ Event::Start(e) => {
+ return Ok(Self {
+ event: Event::Start(e.into_owned()),
+ content: None,
+ })
+ }
+ e => Err(ElementError::NotAStart(e.into_owned()).into()),
+ }
+ }
+}
+
+#[derive(Debug)]
+pub enum ElementError<'e> {
+ NotAStart(Event<'e>),
+}