// This file is generated by ValueConversions_cpp.template.

// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include {{format_include(config.protocol.package, "Protocol")}}

#include <algorithm>
#include <climits>
#include <string>

//#include "ValueConversions.h"
//#include "Values.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

{% for namespace in config.protocol.namespace %}
}  // namespce
{% endfor %}


namespace {{config.crdtp.namespace}} {

namespace {

using {{"::".join(config.protocol.namespace)}}::Binary;
using {{"::".join(config.protocol.namespace)}}::Object;
using {{"::".join(config.protocol.namespace)}}::Value;
using {{"::".join(config.protocol.namespace)}}::String;
using {{"::".join(config.protocol.namespace)}}::DictionaryValue;
using {{"::".join(config.protocol.namespace)}}::FundamentalValue;
using {{"::".join(config.protocol.namespace)}}::StringValue;
using {{"::".join(config.protocol.namespace)}}::StringUtil;
//using {{"::".join(config.protocol.namespace)}}::EncodeString;

std::unique_ptr<Value> ReadValue(DeserializerState* state) {
  cbor::CBORTokenizer* tokenizer = state->tokenizer();
  switch (tokenizer->TokenTag()) {
    case cbor::CBORTokenTag::TRUE_VALUE:
      return FundamentalValue::create(true);
    case cbor::CBORTokenTag::FALSE_VALUE:
      return FundamentalValue::create(false);
    case cbor::CBORTokenTag::NULL_VALUE:
      return Value::null();
    case cbor::CBORTokenTag::INT32:
      return FundamentalValue::create(tokenizer->GetInt32());
    case cbor::CBORTokenTag::DOUBLE:
      return FundamentalValue::create(tokenizer->GetDouble());
    case cbor::CBORTokenTag::STRING8: {
      const auto str = tokenizer->GetString8();
      return StringValue::create(StringUtil::fromUTF8(str.data(), str.size()));
    }
    case cbor::CBORTokenTag::STRING16: {
      const auto str = tokenizer->GetString16WireRep();
      return StringValue::create(StringUtil::fromUTF16LE(reinterpret_cast<const uint16_t*>(str.data()), str.size() / 2));
    }
    case cbor::CBORTokenTag::ENVELOPE: {
      const auto env = tokenizer->GetEnvelope();
      return Value::parseBinary(env.data(), env.size());
    }
    // Intentionally not supported.
    case cbor::CBORTokenTag::BINARY:
    // Should not be encountered outside of envelope.
    case cbor::CBORTokenTag::MAP_START:
    case cbor::CBORTokenTag::ARRAY_START:
    default:
      state->RegisterError(Error::CBOR_UNSUPPORTED_VALUE);
      return nullptr;
  }
}

}  // namespace

// static
bool ProtocolTypeTraits<std::unique_ptr<Value>>::Deserialize(
    DeserializerState* state, std::unique_ptr<Value>* value) {
  auto result = ReadValue(state);
  if (!result)
    return false;
  *value = std::move(result);
  return true;
}

// static
void ProtocolTypeTraits<std::unique_ptr<Value>>::Serialize(
    const std::unique_ptr<Value>& value, std::vector<uint8_t>* bytes) {
  value->AppendSerialized(bytes);
}

// static
bool ProtocolTypeTraits<std::unique_ptr<DictionaryValue>>::Deserialize(
    DeserializerState* state, std::unique_ptr<DictionaryValue>* value) {
  std::unique_ptr<Value> res;
  if (!ProtocolTypeTraits<std::unique_ptr<Value>>::Deserialize(state, &res))
    return false;
  *value = DictionaryValue::cast(std::move(res));
  return true;
}

// static
void ProtocolTypeTraits<std::unique_ptr<DictionaryValue>>::Serialize(
    const std::unique_ptr<DictionaryValue>& value, std::vector<uint8_t>* bytes) {
  value->AppendSerialized(bytes);
}

// static
bool ProtocolTypeTraits<std::unique_ptr<Object>>::Deserialize(DeserializerState* state, std::unique_ptr<Object>* value) {
  auto res = DictionaryValue::create();
  if (ProtocolTypeTraits<std::unique_ptr<DictionaryValue>>::Deserialize(state, &res)) {
    *value = std::make_unique<Object>(std::move(res));
    return true;
  }
  return false;
}

void ProtocolTypeTraits<std::unique_ptr<Object>>::Serialize(const std::unique_ptr<Object>& value, std::vector<uint8_t>* bytes) {
  value->AppendSerialized(bytes);
}

}  // namespace {{config.crdtp.namespace}}
