#pragma once #include #include #include #include namespace mbgl { namespace style { namespace conversion { template <> class ConversionTraits { public: static bool isUndefined(const JSValue* value) { return value->IsNull(); } static bool isArray(const JSValue* value) { return value->IsArray(); } static std::size_t arrayLength(const JSValue* value) { return value->Size(); } static const JSValue* arrayMember(const JSValue* value, std::size_t i) { return &(*value)[rapidjson::SizeType(i)]; } static bool isObject(const JSValue* value) { return value->IsObject(); } static optional objectMember(const JSValue* value, const char * name) { if (!value->HasMember(name)) { return {}; } const JSValue* const& member = &(*value)[name]; return {member}; } template static optional eachMember(const JSValue* value, Fn&& fn) { assert(value->IsObject()); for (const auto& property : value->GetObject()) { optional result = fn({ property.name.GetString(), property.name.GetStringLength() }, &property.value); if (result) { return result; } } return {}; } static optional toBool(const JSValue* value) { if (!value->IsBool()) { return {}; } return value->GetBool(); } static optional toNumber(const JSValue* value) { if (!value->IsNumber()) { return {}; } return value->GetDouble(); } static optional toDouble(const JSValue* value) { if (!value->IsNumber()) { return {}; } return value->GetDouble(); } static optional toString(const JSValue* value) { if (!value->IsString()) { return {}; } return {{ value->GetString(), value->GetStringLength() }}; } static optional toValue(const JSValue* value) { switch (value->GetType()) { case rapidjson::kNullType: case rapidjson::kFalseType: return { false }; case rapidjson::kTrueType: return { true }; case rapidjson::kStringType: return { std::string { value->GetString(), value->GetStringLength() } }; case rapidjson::kNumberType: if (value->IsUint64()) return { value->GetUint64() }; if (value->IsInt64()) return { value->GetInt64() }; return { value->GetDouble() }; default: return {}; } } static optional toGeoJSON(const JSValue* value, Error& error) { try { return mapbox::geojson::convert(*value); } catch (const std::exception& ex) { error = { ex.what() }; return {}; } } }; template optional convert(const JSValue& value, Error& error, Args&&...args) { return convert(Convertible(&value), error, std::forward(args)...); } } // namespace conversion } // namespace style } // namespace mbgl