Jelajahi Sumber

Make SectionPairRow class serializable

Patrick-Christopher Mattulat 2 tahun lalu
induk
melakukan
6f2b271459

+ 7 - 2
include/ls-std/io/section-pair/model/SectionPairRow.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-08
-* Changed:         2023-02-12
+* Changed:         2023-02-13
 *
 * */
 
@@ -11,6 +11,7 @@
 #define LS_STD_SECTION_PAIR_ROW_HPP
 
 #include <ls-std/core/Class.hpp>
+#include <ls-std/core/interface/ISerializable.hpp>
 #include <ls-std/io/section-pair/SectionPairRowEnumType.hpp>
 #include <ls-std/io/section-pair/SectionPairTypes.hpp>
 #include <ls-std/io/section-pair/model/SectionPairRowValue.hpp>
@@ -19,7 +20,7 @@
 
 namespace ls::std::io
 {
-  class LS_STD_DYNAMIC_GOAL SectionPairRow : public ls::std::core::Class
+  class LS_STD_DYNAMIC_GOAL SectionPairRow : public ls::std::core::Class, public ls::std::core::interface_type::ISerializable
   {
     public:
 
@@ -30,11 +31,15 @@ namespace ls::std::io
       [[nodiscard]] ::std::shared_ptr<ls::std::io::SectionPairRowValue> getValue();
       [[nodiscard]] bool isList();
       [[nodiscard]] bool isSingleValue();
+      [[nodiscard]] ls::std::core::type::byte_field marshal() override;
       void setKey(const ls::std::io::section_pair_identifier &_key);
+      void setSerializable(const ::std::shared_ptr<ls::std::core::interface_type::ISerializable>& _serializable);
+      void unmarshal(const ls::std::core::type::byte_field &_data) override;
 
     private:
 
       ls::std::io::section_pair_identifier key{};
+      ::std::shared_ptr<ls::std::core::interface_type::ISerializable> serializable{};
       ::std::shared_ptr<ls::std::io::SectionPairRowValue> value{};
 
       void _initValue(const ls::std::io::SectionPairRowEnumType &_type);

+ 27 - 4
source/ls-std/io/section-pair/model/SectionPairRow.cpp

@@ -3,11 +3,13 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-08
-* Changed:         2023-02-12
+* Changed:         2023-02-13
 *
 * */
 
 #include <ls-std/core/evaluator/EmptyStringArgumentEvaluator.hpp>
+#include <ls-std/core/evaluator/NullPointerArgumentEvaluator.hpp>
+#include <ls-std/core/evaluator/NullPointerEvaluator.hpp>
 #include <ls-std/core/exception/IllegalArgumentException.hpp>
 #include <ls-std/io/section-pair/evaluator/SectionPairIdentifierArgumentEvaluator.hpp>
 #include <ls-std/io/section-pair/model/SectionPairRow.hpp>
@@ -42,18 +44,39 @@ bool ls::std::io::SectionPairRow::isSingleValue()
   return this->value->getType() == ls::std::io::SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE;
 }
 
+ls::std::core::type::byte_field ls::std::io::SectionPairRow::marshal()
+{
+  ::std::string message = "member \"serializable\" for marshal attempt is null!";
+  ls::std::core::NullPointerEvaluator{::std::reinterpret_pointer_cast<void>(this->serializable), message}.evaluate();
+  return this->serializable->marshal();
+}
+
 void ls::std::io::SectionPairRow::setKey(const ls::std::io::section_pair_identifier &_key)
 {
   this->_setKey(_key);
 }
 
+void ls::std::io::SectionPairRow::setSerializable(const ::std::shared_ptr<ls::std::core::interface_type::ISerializable> &_serializable)
+{
+  ::std::string message = this->getClassName() + ": argument \"_serializable\" is null!";
+  ls::std::core::NullPointerArgumentEvaluator{::std::reinterpret_pointer_cast<void>(_serializable), message}.evaluate();
+  this->serializable = _serializable;
+}
+
+void ls::std::io::SectionPairRow::unmarshal(const ls::std::core::type::byte_field &_data)
+{
+  ::std::string message = this->getClassName() + ": member \"serializable\" for unmarshal attempt is null!";
+  ls::std::core::NullPointerEvaluator{::std::reinterpret_pointer_cast<void>(this->serializable), message}.evaluate();
+  this->serializable->unmarshal(_data);
+}
+
 void ls::std::io::SectionPairRow::_initValue(const ls::std::io::SectionPairRowEnumType &_type)
 {
   switch (_type)
   {
     case SECTION_PAIR_ROW_NOT_IMPLEMENTED:
     {
-      throw ls::std::core::IllegalArgumentException{"default row enum type can not be set!"};
+      throw ls::std::core::IllegalArgumentException{this->getClassName() + ": default row enum type can not be set!"};
     }
     case SECTION_PAIR_ROW_LIST_VALUE:
     {
@@ -70,7 +93,7 @@ void ls::std::io::SectionPairRow::_initValue(const ls::std::io::SectionPairRowEn
 
 void ls::std::io::SectionPairRow::_setKey(const ls::std::io::section_pair_identifier &_key)
 {
-  ls::std::core::EmptyStringArgumentEvaluator{_key, "passed key identifier for section pair row is empty!"}.evaluate();
-  ls::std::io::SectionPairIdentifierArgumentEvaluator(_key, "section pair key identifier \"" + _key + "\" contains invalid characters!").evaluate();
+  ls::std::core::EmptyStringArgumentEvaluator{_key, this->getClassName() + ": passed key identifier is empty!"}.evaluate();
+  ls::std::io::SectionPairIdentifierArgumentEvaluator(_key, this->getClassName() + ": section pair key identifier \"" + _key + "\" contains invalid characters!").evaluate();
   this->key = _key;
 }

+ 112 - 1
test/cases/io/section-pair/model/SectionPairRowTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-08
-* Changed:         2023-02-12
+* Changed:         2023-02-13
 *
 * */
 
@@ -12,6 +12,7 @@
 #include <ls-std/ls-std-io.hpp>
 
 using namespace ls::std::core;
+using namespace ls::std::core::type;
 using namespace ls::std::io;
 using namespace ::std;
 
@@ -95,6 +96,50 @@ namespace
     ASSERT_FALSE(SectionPairRow("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE).isList());
   }
 
+  TEST_F(SectionPairRowTest, marshal_single_value)
+  {
+    shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("favourite-color", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+    shared_ptr<SectionPairRowSingleValue> singleValue = dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue());
+    singleValue->set("blue");
+    singleValue->setSerializable(make_shared<SerializableSectionPairRowSingleValue>(singleValue));
+    row->setSerializable(make_shared<SerializableSectionPairRow>(row));
+
+    ASSERT_STREQ("favourite-color=blue", row->marshal().c_str());
+  }
+
+  TEST_F(SectionPairRowTest, marshal_list_value)
+  {
+    shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("favourite-colors", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
+    shared_ptr<SectionPairRowListValue> listValue = dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
+    listValue->add("blue");
+    listValue->add("red");
+    listValue->add("purple");
+    listValue->setSerializable(make_shared<SerializableSectionPairRowListValue>(listValue));
+    row->setSerializable(make_shared<SerializableSectionPairRow>(row));
+
+    string expected = "favourite-colors:" + NewLine::get() + "  blue" + NewLine::get() + "  red" + NewLine::get() + "  purple" + NewLine::get();
+
+    ASSERT_STREQ(expected.c_str(), row->marshal().c_str());
+  }
+
+  TEST_F(SectionPairRowTest, marshal_no_serializable)
+  {
+    SectionPairRow row("hobbies", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
+
+    EXPECT_THROW(
+        {
+          try
+          {
+            byte_field data = row.marshal();
+          }
+          catch (const NullPointerException &_exception)
+          {
+            throw;
+          }
+        },
+        NullPointerException);
+  }
+
   TEST_F(SectionPairRowTest, setKey)
   {
     SectionPairRow row("hobbies", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
@@ -138,4 +183,70 @@ namespace
         },
         IllegalArgumentException);
   }
+
+  TEST_F(SectionPairRowTest, setSerializable_no_reference)
+  {
+    SectionPairRow row("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+
+    EXPECT_THROW(
+        {
+          try
+          {
+            row.setSerializable(nullptr);
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(SectionPairRowTest, unmarshal_single_value)
+  {
+    shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+    row->setSerializable(make_shared<SerializableSectionPairRow>(row));
+    shared_ptr<SectionPairRowSingleValue> singleValue = dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue()); // TODO: should be created automatically
+    singleValue->setSerializable(make_shared<SerializableSectionPairRowSingleValue>(singleValue));
+
+    row->unmarshal("favourite-color=blue");
+
+    ASSERT_STREQ("favourite-color", row->getKey().c_str());
+    ASSERT_STREQ("blue", singleValue->get().c_str());
+  }
+
+  TEST_F(SectionPairRowTest, unmarshal_list_value)
+  {
+    shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
+    row->setSerializable(make_shared<SerializableSectionPairRow>(row));
+    shared_ptr<SectionPairRowListValue> listValue = dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
+    listValue->setSerializable(make_shared<SerializableSectionPairRowListValue>(listValue));
+
+    string data = "favourite-colors:" + NewLine::get() + "  blue" + NewLine::get() + "  red" + NewLine::get() + "  purple" + NewLine::get();
+    row->unmarshal(data);
+
+    ASSERT_STREQ("favourite-colors", row->getKey().c_str());
+    ASSERT_STREQ("blue", listValue->get(0).c_str());
+    ASSERT_STREQ("red", listValue->get(1).c_str());
+    ASSERT_STREQ("purple", listValue->get(2).c_str());
+    ASSERT_EQ(3, listValue->getSize());
+  }
+
+  TEST_F(SectionPairRowTest, unmarshal_no_serializable)
+  {
+    SectionPairRow row("hobbies", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
+
+    EXPECT_THROW(
+        {
+          try
+          {
+            row.unmarshal("hobbies:");
+          }
+          catch (const NullPointerException &_exception)
+          {
+            throw;
+          }
+        },
+        NullPointerException);
+  }
 }

+ 5 - 5
test/cases/io/section-pair/serialization/SerializableSectionPairRowTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-02-12
-* Changed:         2023-02-12
+* Changed:         2023-02-13
 *
 * */
 
@@ -57,7 +57,7 @@ namespace
   TEST_F(SerializableSectionPairRowTest, marshal_single_value)
   {
     shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("favourite-color", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
-    shared_ptr<SectionPairRowSingleValue> singleValue = ::std::dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue());
+    shared_ptr<SectionPairRowSingleValue> singleValue = dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue());
     singleValue->set("blue");
     singleValue->setSerializable(make_shared<SerializableSectionPairRowSingleValue>(singleValue));
     SerializableSectionPairRow serializable{row};
@@ -68,7 +68,7 @@ namespace
   TEST_F(SerializableSectionPairRowTest, marshal_list_value)
   {
     shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("favourite-colors", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
-    shared_ptr<SectionPairRowListValue> listValue = ::std::dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
+    shared_ptr<SectionPairRowListValue> listValue = dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
     listValue->add("blue");
     listValue->add("red");
     listValue->add("purple");
@@ -83,7 +83,7 @@ namespace
   TEST_F(SerializableSectionPairRowTest, unmarshal_single_value)
   {
     shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_SINGLE_VALUE);
-    shared_ptr<SectionPairRowSingleValue> singleValue = ::std::dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue());
+    shared_ptr<SectionPairRowSingleValue> singleValue = dynamic_pointer_cast<SectionPairRowSingleValue>(row->getValue());
     singleValue->setSerializable(make_shared<SerializableSectionPairRowSingleValue>(singleValue));
     SerializableSectionPairRow serializable{row};
 
@@ -96,7 +96,7 @@ namespace
   TEST_F(SerializableSectionPairRowTest, unmarshal_list_value)
   {
     shared_ptr<SectionPairRow> row = make_shared<SectionPairRow>("tmp-key", SectionPairRowEnumType::SECTION_PAIR_ROW_LIST_VALUE);
-    shared_ptr<SectionPairRowListValue> listValue = ::std::dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
+    shared_ptr<SectionPairRowListValue> listValue = dynamic_pointer_cast<SectionPairRowListValue>(row->getValue());
     listValue->setSerializable(make_shared<SerializableSectionPairRowListValue>(listValue));
     SerializableSectionPairRow serializable{row};