From 9807b378cb3220b5e558e2673fdcaeaf8e66ee3a Mon Sep 17 00:00:00 2001
From: Neshura <neshura@neshweb.net>
Date: Fri, 29 Sep 2023 00:21:42 +0200
Subject: [PATCH 1/2] Flat Tag Serializing

---
 src/main.rs         | 13 ++++++-
 src/metadata/mod.rs | 95 +++++++++++++++++++++++++++++----------------
 2 files changed, 73 insertions(+), 35 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 2560a78..9445c7d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -281,8 +281,19 @@ impl eframe::App for Generator<'_> {
             tags: Vec<String>,
             characters: Vec<String>,
             */
-            text_input(ui, &mut self.metadata[0].genre, "Genre", false);
             // TODO tag list (List of bordered labels with plus that opens a new text edit)
+
+            ui.horizontal(|row| {
+                row.label("Tags:");
+                for mut tag in &mut self.metadata[0].tags {
+                    text_input(row, &mut tag, "", false);
+                }
+                if row.button("+").clicked() {
+                    &self.metadata[0].tags.push("".to_string());
+                };
+            });
+
+            text_input(ui, &mut self.metadata[0].genre, "Genre", false);
             ui.horizontal(|row| {
                 row.label("Page Count:");
                 if row.button("-").clicked() {
diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs
index 1d0dd42..bd44cac 100644
--- a/src/metadata/mod.rs
+++ b/src/metadata/mod.rs
@@ -1,11 +1,11 @@
 use std::{fs::File, io::{Write, Cursor}};
 use quick_xml::{se::Serializer, events::BytesStart};
 use serde::{Serialize, Deserialize};
+use serde::ser::{SerializeSeq, SerializeStruct};
 
 use serde_xml_rs::{to_string, to_writer};
 
-
-#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
+#[derive(Debug, Deserialize, PartialEq, Clone)]
 pub(crate) struct Metadata<'a> {
     #[serde(rename = "@xmlns:xsi")]
     xsi: &'a str,
@@ -13,70 +13,38 @@ pub(crate) struct Metadata<'a> {
     #[serde(rename = "@xsi:noNamespaceSchemaLocation")]
     namespace: &'a str,
 
-    #[serde(rename(serialize="Title"))]
     pub(crate) title: String,
 
-    #[serde(rename(serialize="Series"))]
     pub(crate) series: String,
 
-    #[serde(rename(serialize="Number"))]
     pub(crate) number: u16,
 
-    #[serde(rename(serialize="Count"))]
     pub(crate) count: i16,
 
-    #[serde(rename(serialize="Volume"))]
     pub(crate) volume: i16,
 
-    #[serde(rename(serialize="Summary"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) summary: Option<String>,
 
-    #[serde(rename(serialize="Year"))]
     pub(crate) year: i16,
-    #[serde(rename(serialize="Month"))]
     pub(crate) month: i8,
-    #[serde(rename(serialize="Day"))]
     pub(crate) day: i8,
 
-    #[serde(rename(serialize="Writer"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) writer: Option<String>,
-
-    #[serde(rename(serialize="Letterer"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) letterer: Option<String>,
-
-    #[serde(rename(serialize="Editor"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) editor: Option<String>,
-
-    #[serde(rename(serialize="Translator"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) translator: Option<String>,
-
-    #[serde(rename(serialize="Publisher"))]
-    #[serde(skip_serializing_if = "Option::is_none")]
     pub(crate) publisher: Option<String>,
 
-    #[serde(rename(serialize="Genre"))]
     pub(crate) genre: String,
 
-    #[serde(rename(serialize="Tags"))]
-    #[serde(skip_serializing_if = "Vec::is_empty")]
     pub(crate) tags: Vec<String>,
 
-    #[serde(rename(serialize="PageCount"))]
     pub(crate) page_count: u16,
 
-    #[serde(flatten)]
     pub(crate) language: LanguageISO,
 
-    #[serde(rename(serialize="Characters"))]
-    #[serde(skip_serializing_if = "Vec::is_empty")]
     pub(crate) characters: Vec<String>,
 
-    #[serde(flatten)]
     pub(crate) age_rating: AgeRating
 }
 
@@ -109,6 +77,65 @@ impl Default for Metadata<'_> {
     }
 }
 
+impl Serialize for Metadata<'_> {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
+        let mut out_state = serializer.serialize_struct("Metadata", 22)?;
+        out_state.serialize_field("@xmlns:xsi", &self.xsi)?;
+        out_state.serialize_field("@xsi:noNamespaceSchemaLocation", &self.namespace)?;
+        out_state.serialize_field("Title", &self.title)?;
+        out_state.serialize_field("Series", &self.series)?;
+        out_state.serialize_field("Number", &self.number)?;
+        out_state.serialize_field("Count", &self.count)?;
+        out_state.serialize_field("Volume", &self.volume)?;
+
+        if self.summary.is_some() {
+            out_state.serialize_field("Summary", &self.summary)?;
+        }
+
+        out_state.serialize_field("Year", &self.year)?;
+        out_state.serialize_field("Month", &self.month)?;
+        out_state.serialize_field("Day", &self.day)?;
+
+        if self.writer.is_some() {
+            out_state.serialize_field("Writer", &self.writer)?;
+        }
+
+        if self.letterer.is_some() {
+            out_state.serialize_field("Letterer", &self.letterer)?;
+        }
+
+        if self.editor.is_some() {
+            out_state.serialize_field("Editor", &self.editor)?;
+        }
+
+        if self.translator.is_some() {
+            out_state.serialize_field("Translator", &self.translator)?;
+        }
+
+        if self.publisher.is_some() {
+            out_state.serialize_field("Publisher", &self.publisher)?;
+        }
+
+        out_state.serialize_field("Genre", &self.genre)?;
+
+        if self.tags.len() != 0 {
+            out_state.serialize_field("Tags", &self.tags.join(", "))?;
+        }
+
+        out_state.serialize_field("PageCount", &self.page_count)?;
+
+        out_state.serialize_field("LanguageISO", &self.language.to_string())?;
+
+        if self.characters.len() != 0 {
+            out_state.serialize_field("Characters", &self.characters.join(", "))?;
+        }
+
+        out_state.serialize_field("AgeRating", &self.age_rating.to_string())?;
+
+        out_state.end()
+    }
+}
+
 impl Metadata<'_> {
     pub(crate) fn save_to_xml(&self, path: &str) {
         let mut file = File::create(path).unwrap();

From a67d9ae25d0e82827ae4570c49de808babfe58d9 Mon Sep 17 00:00:00 2001
From: Neshura <neshura@neshweb.net>
Date: Fri, 29 Sep 2023 00:26:00 +0200
Subject: [PATCH 2/2] Workaround for Clearing Tag Vector of empty elements

---
 src/main.rs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main.rs b/src/main.rs
index 9445c7d..b9764a1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -285,11 +285,12 @@ impl eframe::App for Generator<'_> {
 
             ui.horizontal(|row| {
                 row.label("Tags:");
+                &mut self.metadata[0].tags.retain(|x| x != "");
                 for mut tag in &mut self.metadata[0].tags {
                     text_input(row, &mut tag, "", false);
                 }
                 if row.button("+").clicked() {
-                    &self.metadata[0].tags.push("".to_string());
+                    &self.metadata[0].tags.push(" ".to_string());
                 };
             });