void rewriteLocalScheme(rapidjson::Value &value, rapidjson::Document::AllocatorType &allocator) {
    ASSERT_TRUE(value.IsString());
    auto string = std::string { value.GetString(),value.GetStringLength() };
    if (string.compare(0, 8, "local://") == 0) {
        string.replace(0, 8, "http://127.0.0.1:2900/");
        value.SetString(string.data(), string.size(), allocator);
    }
}
static void parseValue(SettingValue &value, const rapidjson::Value &json_val)
{
    if (json_val.IsInt())
        value = json_val.GetInt();
    else if (json_val.IsString())
        value = std::string(json_val.GetString(), json_val.GetStringLength());
    else if (json_val.IsBool())
        value = json_val.GetBool();
    else if (json_val.IsArray())
    {
        SettingList value_list;

        for (auto it = json_val.Begin(); it != json_val.End(); ++it)
        {
            SettingValue child_val;
            parseValue(child_val, *it);
            value_list.push_back(child_val);
        }

        value = value_list;
    }
    else if (json_val.IsObject())
    {
        SettingMap value_map;

        for (auto it = json_val.MemberBegin(); it != json_val.MemberEnd(); ++it)
        {
            SettingValue child_val;
            parseValue(child_val, it->value);
            value_map[it->name.GetString()] = child_val;
        }

        value = value_map;
    }
    else
        throw std::runtime_error("Unexpected JSON value type.");
}
void ConvertToMsgPack(const rapidjson::Value& json, msgpack::object& object, msgpack::zone& zone)
{
	switch (json.GetType())
	{
		case rapidjson::kFalseType:
			object = false;
			break;

		case rapidjson::kTrueType:
			object = true;
			break;

		case rapidjson::kNumberType:
		{
			if (json.IsInt())
			{
				object = json.GetInt();
			}
			else if (json.IsUint())
			{
				object = json.GetUint();
			}
			else if (json.IsInt64())
			{
				object = json.GetInt64();
			}
			else if (json.IsUint64())
			{
				object = json.GetUint64();
			}
			else if (json.IsDouble())
			{
				object = json.GetDouble();
			}

			break;
		}

		case rapidjson::kStringType:
			// we allocate with 'zone', otherwise the std::string's raw pointer gets used, which won't work as it gets destructed later on
			object = msgpack::object(std::string(json.GetString(), json.GetStringLength()), zone);
			break;

		case rapidjson::kObjectType:
		{
			std::map<std::string, msgpack::object> list;

			for (auto it = json.MemberBegin(); it != json.MemberEnd(); it++)
			{
				msgpack::object newObject;
				ConvertToMsgPack(it->value, newObject, zone);

				list.insert({ it->name.GetString(), newObject });
			}

			object = msgpack::object(list, zone);

			break;
		}

		case rapidjson::kArrayType:
		{
			std::vector<msgpack::object> list;

			for (auto it = json.Begin(); it != json.End(); it++)
			{
				msgpack::object newObject;
				ConvertToMsgPack(*it, newObject, zone);

				list.push_back(newObject);
			}

			object = msgpack::object(list, zone);

			break;
		}

		default:
			object = msgpack::type::nil();
			break;
	}
}
 bool clone_value(rapidjson::Value & output, const rapidjson::Value & input, rapidjson::Value::AllocatorType & allocator)
 {
     if(&output == &input)
     {
         return false;
     }
     
     if(input.IsNull())
     {
         output.SetNull();
     }
     else if(input.IsInt64())
     {
         output.SetInt(input.GetInt64());
     }
     else if(input.IsInt())
     {
         output.SetInt(input.GetInt());
     }
     else if(input.IsDouble())
     {
         output.SetDouble(input.GetDouble());
     }
     else if(input.IsBool())
     {
         output.SetBool(input.GetBool());
     }
     else if(input.IsString())
     {
         output.SetString(input.GetString(), input.GetStringLength(), allocator);
     }
     else if(input.IsArray())
     {
         rapidjson::Value temp;
         output.SetArray();
         output.Reserve(input.Size(), allocator);
         for(rapidjson::SizeType i = 0; i < input.Size(); ++i)
         {
             clone_value(temp, input[i], allocator);
             output.PushBack(temp, allocator);
         }
     }
     else if(input.IsObject())
     {
         output.SetObject();
         
         rapidjson::Value key, val;
         for(rapidjson::Value::ConstMemberIterator it = input.MemberBegin();
             it != input.MemberEnd(); ++it)
         {
             clone_value(key, it->name, allocator);
             clone_value(val, it->value, allocator);
             
             output.AddMember(key, val, allocator);
         }
     }
     else
     {
         assert(false && "shuldn't execute to here.");
         return false;
     }
     return true;
 }