patch

From 62bbd6f93068750223e037f01c7ffc2293ebc7d7 Mon Sep 17 00:00:00 2001
From: Linus Jahn <lnj@kaidan.im>
Date: Sun, 31 Jul 2022 15:06:41 +0200
Subject: [PATCH] More error handling

---
 codegen.py         | 32 +++++++++++++++++++++++++-------
 include/xmlserde.h |  1 +
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/codegen.py b/codegen.py
index ad9f84c..5c6f365 100644
--- a/codegen.py
+++ b/codegen.py
@@ -154,23 +154,38 @@ def write_element_deserializer(f: TextIO, el: Element):
         if attribute.required:
             writeln(f, f"if (!input.hasAttribute(QStringLiteral(\"{attribute.xml_name}\")))", 1)
             writeln(f, f"return XmlDeserializeError {{ QStringLiteral(\"{el.full_name}::{attribute.name}: Missing required attribute \\\"{attribute.xml_name}\\\"!\"), XmlDeserializeError::MissingAttribute }};", 2)
-            writeln(f, f"auto {attribute.name}Result = {attribute.serde_type}::deserialize(input.attribute(QStringLiteral(\"{attribute.xml_name}\"))));", 1)
+            writeln(f, f"auto {attribute.name}Result = {attribute.serde_type}::deserialize(input.attribute(QStringLiteral(\"{attribute.xml_name}\")));", 1)
             writeln(f, f"if (std::holds_alternative<XmlDeserializeError>({attribute.name}Result))", 1)
-            writeln(f, f"return std::get<XmlDeserializeError>(std::move({attribute.name}Result))", 2)
-            # writeln(f, f"auto {attribute.name} = std::get<{attribute.type}>(std::move({attribute.name}Result));", 1)
+            writeln(f, f"return std::get<XmlDeserializeError>(std::move({attribute.name}Result));", 2)
         else:
             # optional
             writeln(f, f"{attribute.store_type} {attribute.name};")
             writeln(f, f"if (input.hasAttribute(QStringLiteral(\"{attribute.xml_name}\"))) {{", 1)
-            writeln(f, f"auto {attribute.name}Result = {attribute.serde_type}::deserialize(input.attribute(QStringLiteral(\"{attribute.xml_name}\"))));", 2)
+            writeln(f, f"auto {attribute.name}Result = {attribute.serde_type}::deserialize(input.attribute(QStringLiteral(\"{attribute.xml_name}\")));", 2)
             writeln(f, f"if (std::holds_alternative<XmlDeserializeError>({attribute.name}Result))", 2)
             writeln(f, f"return std::get<XmlDeserializeError>(std::move({attribute.name}Result))", 3)
             writeln(f, f"{attribute.name} = std::get<{attribute.type}>(std::move({attribute.name}Result));")
             writeln(f, f"}}", 1)
+        writeln(f)
 
     if el.content:
-        writeln(f, f"auto {el.content.name} = XmlUtils::deserialize<XmlUtils::{el.content.type_occurrence.to_string()}, "
-                   f"{el.content.type}, {el.content.serde_type}>(input.text());", 1)
+        if el.content.required:
+            result_var = f"{el.content.name}Result"
+
+            writeln(f, "if (input.text().isEmpty())", 1)
+            writeln(f, f"return XmlDeserializeError {{ QStringLiteral(\"{el.full_name}: Missing required element content!\"), XmlDeserializeError::MissingContent }};", 2)
+            writeln(f, f"auto {result_var} = {el.content.serde_type}::deserialize(input.text());")
+            writeln(f, f"if (std::holds_alternative<XmlDeserializeError>({result_var}))", 2)
+            writeln(f, f"return std::get<XmlDeserializeError>(std::move({result_var}));", 3)
+        else:
+            writeln(f, f"{el.content.store_type} {el.content.name};", 1)
+            writeln(f, f"if (auto text = input.text(); !text.isEmpty()) {{", 1)
+            writeln(f, f"auto contentResult = {el.content.serde_type}::deserialize(text);", 2)
+            writeln(f, f"if (std::holds_alternative<XmlDeserializeError>(contentResult))", 2)
+            writeln(f, f"return std::get<XmlDeserializeError>(std::move(contentResult));", 3)
+            writeln(f, f"{el.content.name} = std::get<{el.content.type}>(std::move(contentResult));", 2)
+            writeln(f, "}}", 1)
+        writeln(f)
 
     for subel in el.sub_els:
         writeln(f, f"auto {subel.name} = XmlUtils::deserialize<XmlUtils::{subel.type_occurrence.to_string()}, "
@@ -183,7 +198,10 @@ def write_element_deserializer(f: TextIO, el: Element):
         else:
             f.write(f"{a.name}, ")
     if el.content:
-        f.write(f"{el.content.name}, ")
+        if el.content.required:
+            f.write(f"std::get<{el.content.type}>(std::move({el.content.name}Result)), ")
+        else:
+            f.write(f"{el.content.name}, ")
     for sub_el in el.sub_els:
         f.write(f"{sub_el.name}, ")
     writeln(f, "};")
diff --git a/include/xmlserde.h b/include/xmlserde.h
index a6c4f3a..27950a4 100644
--- a/include/xmlserde.h
+++ b/include/xmlserde.h
@@ -15,6 +15,7 @@ struct XmlDeserializeError {
         TooFewElements,
         TooManyElements,
         MissingAttribute,
+        MissingContent,
         InvalidEnumValue,
     } type;
 };
-- 
2.36.1