// GENERATED FILE
// This file generated by DomDistillerJs protoc plugin.
#include "test_sample.pb.h"

// base dependencies
#include "base/values.h"

#include <memory>
#include <string>
#include <utility>

namespace dom_distiller {
  namespace test_sample {
    namespace proto {
      namespace json {
        class TypeTest {
         public:
          class Message {
           public:
            static bool ReadFromValue(const base::Value* json, dom_distiller::test_sample::proto::TypeTest::Message* message) {
              const base::DictionaryValue* dict;
              if (!json->GetAsDictionary(&dict)) goto error;
              if (dict->HasKey("1")) {
                bool field_value;
                if (!dict->GetBoolean("1", &field_value)) {
                  goto error;
                }
                message->set_dummy(field_value);
              }
              return true;

            error:
              return false;
            }

            static std::unique_ptr<base::DictionaryValue> WriteToValue(const dom_distiller::test_sample::proto::TypeTest::Message& message) {
              std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
              if (message.has_dummy()) {
                dict->SetBoolean("1", message.dummy());
              }
              return dict;
            }
          };

          static bool ReadFromValue(const base::Value* json, dom_distiller::test_sample::proto::TypeTest* message) {
            const base::DictionaryValue* dict;
            if (!json->GetAsDictionary(&dict)) goto error;
            if (dict->HasKey("1")) {
              float field_value;
              if (!dict->GetDouble("1", &field_value)) {
                goto error;
              }
              message->set_float_value(field_value);
            }
            if (dict->HasKey("2")) {
              double field_value;
              if (!dict->GetDouble("2", &field_value)) {
                goto error;
              }
              message->set_double_value(field_value);
            }
            if (dict->HasKey("3")) {
              int field_value;
              if (!dict->GetInteger("3", &field_value)) {
                goto error;
              }
              message->set_int32_value(field_value);
            }
            if (dict->HasKey("4")) {
              bool field_value;
              if (!dict->GetBoolean("4", &field_value)) {
                goto error;
              }
              message->set_bool_value(field_value);
            }
            if (dict->HasKey("5")) {
              std::string field_value;
              if (!dict->GetString("5", &field_value)) {
                goto error;
              }
              message->set_string_value(field_value);
            }
            if (dict->HasKey("6")) {
              const base::Value* inner_message_value;
              if (!dict->Get("6", &inner_message_value)) {
                goto error;
              }
              if (!dom_distiller::test_sample::proto::json::TypeTest::Message::ReadFromValue(inner_message_value, message->mutable_message_value())) {
                goto error;
              }
            }
            return true;

          error:
            return false;
          }

          static std::unique_ptr<base::DictionaryValue> WriteToValue(const dom_distiller::test_sample::proto::TypeTest& message) {
            std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
            if (message.has_float_value()) {
              dict->SetDouble("1", message.float_value());
            }
            if (message.has_double_value()) {
              dict->SetDouble("2", message.double_value());
            }
            if (message.has_int32_value()) {
              dict->SetInteger("3", message.int32_value());
            }
            if (message.has_bool_value()) {
              dict->SetBoolean("4", message.bool_value());
            }
            if (message.has_string_value()) {
              dict->SetString("5", message.string_value());
            }
            if (message.has_message_value()) {
              std::unique_ptr<base::Value> inner_message_value =
                  dom_distiller::test_sample::proto::json::TypeTest::Message::WriteToValue(message.message_value());
              dict->Set("6", std::move(inner_message_value));
            }
            return dict;
          }
        };

        class Repeated {
         public:
          class Message {
           public:
            static bool ReadFromValue(const base::Value* json, dom_distiller::test_sample::proto::Repeated::Message* message) {
              const base::DictionaryValue* dict;
              if (!json->GetAsDictionary(&dict)) goto error;
              if (dict->HasKey("1")) {
                const base::ListValue* field_list;
                if (!dict->GetList("1", &field_list)) {
                  goto error;
                }
                for (size_t i = 0; i < field_list->GetSize(); ++i) {
                  bool field_value;
                  if (!field_list->GetBoolean(i, &field_value)) {
                    goto error;
                  }
                  message->add_dummy(field_value);
                }
              }
              return true;

            error:
              return false;
            }

            static std::unique_ptr<base::DictionaryValue> WriteToValue(const dom_distiller::test_sample::proto::Repeated::Message& message) {
              std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
              {
                auto field_list = std::make_unique<base::ListValue>();
                for (int i = 0; i < message.dummy_size(); ++i) {
                  field_list->AppendBoolean(message.dummy(i));
                }
                dict->Set("1", std::move(field_list));
              }
              return dict;
            }
          };

          static bool ReadFromValue(const base::Value* json, dom_distiller::test_sample::proto::Repeated* message) {
            const base::DictionaryValue* dict;
            if (!json->GetAsDictionary(&dict)) goto error;
            if (dict->HasKey("1")) {
              const base::ListValue* field_list;
              if (!dict->GetList("1", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                float field_value;
                if (!field_list->GetDouble(i, &field_value)) {
                  goto error;
                }
                message->add_float_value(field_value);
              }
            }
            if (dict->HasKey("2")) {
              const base::ListValue* field_list;
              if (!dict->GetList("2", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                double field_value;
                if (!field_list->GetDouble(i, &field_value)) {
                  goto error;
                }
                message->add_double_value(field_value);
              }
            }
            if (dict->HasKey("3")) {
              const base::ListValue* field_list;
              if (!dict->GetList("3", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                int field_value;
                if (!field_list->GetInteger(i, &field_value)) {
                  goto error;
                }
                message->add_int32_value(field_value);
              }
            }
            if (dict->HasKey("4")) {
              const base::ListValue* field_list;
              if (!dict->GetList("4", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                bool field_value;
                if (!field_list->GetBoolean(i, &field_value)) {
                  goto error;
                }
                message->add_bool_value(field_value);
              }
            }
            if (dict->HasKey("5")) {
              const base::ListValue* field_list;
              if (!dict->GetList("5", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                std::string field_value;
                if (!field_list->GetString(i, &field_value)) {
                  goto error;
                }
                message->add_string_value(field_value);
              }
            }
            if (dict->HasKey("6")) {
              const base::ListValue* field_list;
              if (!dict->GetList("6", &field_list)) {
                goto error;
              }
              for (size_t i = 0; i < field_list->GetSize(); ++i) {
                const base::Value* inner_message_value;
                if (!field_list->Get(i, &inner_message_value)) {
                  goto error;
                }
                if (!dom_distiller::test_sample::proto::json::Repeated::Message::ReadFromValue(inner_message_value, message->add_message_value())) {
                  goto error;
                }
              }
            }
            return true;

          error:
            return false;
          }

          static std::unique_ptr<base::DictionaryValue> WriteToValue(const dom_distiller::test_sample::proto::Repeated& message) {
            std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.float_value_size(); ++i) {
                field_list->AppendDouble(message.float_value(i));
              }
              dict->Set("1", std::move(field_list));
            }
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.double_value_size(); ++i) {
                field_list->AppendDouble(message.double_value(i));
              }
              dict->Set("2", std::move(field_list));
            }
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.int32_value_size(); ++i) {
                field_list->AppendInteger(message.int32_value(i));
              }
              dict->Set("3", std::move(field_list));
            }
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.bool_value_size(); ++i) {
                field_list->AppendBoolean(message.bool_value(i));
              }
              dict->Set("4", std::move(field_list));
            }
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.string_value_size(); ++i) {
                field_list->AppendString(message.string_value(i));
              }
              dict->Set("5", std::move(field_list));
            }
            {
              auto field_list = std::make_unique<base::ListValue>();
              for (int i = 0; i < message.message_value_size(); ++i) {
                std::unique_ptr<base::Value> inner_message_value =
                    dom_distiller::test_sample::proto::json::Repeated::Message::WriteToValue(message.message_value(i));
                field_list->Append(std::move(inner_message_value));
              }
              dict->Set("6", std::move(field_list));
            }
            return dict;
          }
        };

      }
    }
  }
}
