From af9f5d8f24f04ad83181700e4d2933b0638fedb9 Mon Sep 17 00:00:00 2001
From: Dmitry <b4tm4n@mail.ru>
Date: Thu, 24 Aug 2023 15:17:54 +0300
Subject: [PATCH] add manual impl Serialize for Question

---
 lib/src/questions.rs | 65 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/lib/src/questions.rs b/lib/src/questions.rs
index de96d11..812f440 100644
--- a/lib/src/questions.rs
+++ b/lib/src/questions.rs
@@ -75,7 +75,7 @@ pub struct BatchInfo {
     pub rating: String,
 }
 
-#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
+#[derive(Debug, Default, Clone, Deserialize, PartialEq)]
 pub struct Question {
     #[serde(default, skip_serializing_if = "u32_is_zero")]
     pub num: u32,
@@ -114,10 +114,6 @@ pub struct Question {
     pub batch_info: BatchInfo,
 }
 
-fn u32_is_zero(num: &u32) -> bool {
-    *num == 0
-}
-
 impl BatchInfo {
     pub fn is_default(&self) -> bool {
         *self == BatchInfo::default()
@@ -150,7 +146,7 @@ impl serde::Serialize for BatchInfo {
     {
         let is_human_readable = serializer.is_human_readable(); 
         let mut flags: BatchFlags = Default::default();
-        let mut len = 1;
+        let mut len = 1; // (+flags)
 
         count_string_fields!((self, flags, len, BatchFlags) <- {
             filename: FILENAME, description: DESCRIPTION, author: AUTHOR, comment: COMMENT, url: URL, date: DATE,
@@ -174,6 +170,63 @@ impl serde::Serialize for BatchInfo {
     }
 }
 
+impl serde::Serialize for Question {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        let is_human_readable = serializer.is_human_readable(); 
+        let mut flags: QuestionFlags = Default::default();
+        let mut len = 6; //(_flags + id + description + answer + num + batch_info)
+
+        if self.num != 0 {
+            flags |= QuestionFlags::NUM;
+        }
+
+        if !self.batch_info.is_default() {
+            flags |= QuestionFlags::BATCH_INFO;
+        }
+
+        count_string_fields!((self, flags, len, QuestionFlags) <- {
+            author: AUTHOR, comment: COMMENT, comment1: COMMENT1, tour: TOUR, url: URL, date: DATE,
+            processed_by: PROCESSED_BY, redacted_by: REDACTED_BY, copyright: COPYRIGHT, theme: THEME,
+            kind: KIND, source: SOURCE, rating: RATING
+        });
+
+        let mut state = serializer.serialize_struct("Question", len)?;
+        
+        if is_human_readable {
+            state.skip_field("_flags")?;
+        } else {
+            state.serialize_field("_flags", &flags.bits())?;
+        }
+
+        if flags.intersects(QuestionFlags::NUM) {
+            state.serialize_field("num", &self.num)?;
+        } else {
+            state.skip_field("num")?;
+        }
+
+        state.serialize_field("id", &self.id)?;
+        state.serialize_field("description", &self.description)?;
+        state.serialize_field("answer", &self.answer)?;
+
+        serialize_fields!((self, flags, state, QuestionFlags) <- {
+            author: AUTHOR, comment: COMMENT, comment1: COMMENT1, tour: TOUR, url: URL, date: DATE,
+            processed_by: PROCESSED_BY, redacted_by: REDACTED_BY, copyright: COPYRIGHT, theme: THEME,
+            kind: KIND, source: SOURCE, rating: RATING, batch_info: BATCH_INFO
+        });
+
+        if flags.intersects(QuestionFlags::BATCH_INFO) {
+            state.serialize_field("batch_info", &self.batch_info)?;
+        } else {
+            state.skip_field("batch_info")?;
+        }
+
+        state.end()
+    }
+}
+
 #[cfg(any(feature = "convert", feature = "convert_async"))]
 pub mod convert_common {
     use super::{BatchInfo, Question};