#pragma once #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { template <> struct Converter> { public: template Result> operator()(const V& value, const std::string& id) const { if (!isObject(value)) { return Error{ "source must be an object" }; } auto typeValue = objectMember(value, "type"); if (!typeValue) { return Error{ "source must have a type" }; } optional type = toString(*typeValue); if (!type) { return Error{ "source type must be a string" }; } if (*type == "raster") { return convertRasterSource(id, value); } else if (*type == "vector") { return convertVectorSource(id, value); } else if (*type == "geojson") { return convertGeoJSONSource(id, value); } else { return Error{ "invalid source type" }; } } private: // A tile source can either specify a URL to TileJSON, or inline TileJSON. template Result> convertURLOrTileset(const V& value) const { auto urlVal = objectMember(value, "url"); if (!urlVal) { Result tileset = convert(value); if (!tileset) { return tileset.error(); } return *tileset; } optional url = toString(*urlVal); if (!url) { return Error{ "source url must be a string" }; } return *url; } template Result> convertRasterSource(const std::string& id, const V& value) const { Result> urlOrTileset = convertURLOrTileset(value); if (!urlOrTileset) { return urlOrTileset.error(); } uint16_t tileSize = util::tileSize; auto tileSizeValue = objectMember(value, "tileSize"); if (tileSizeValue) { optional size = toNumber(*tileSizeValue); if (!size || *size < 0 || *size > std::numeric_limits::max()) { return Error{ "invalid tileSize" }; } tileSize = *size; } return std::make_unique(id, std::move(*urlOrTileset), tileSize); } template Result> convertVectorSource(const std::string& id, const V& value) const { Result> urlOrTileset = convertURLOrTileset(value); if (!urlOrTileset) { return urlOrTileset.error(); } return std::make_unique(id, std::move(*urlOrTileset)); } template Result> convertGeoJSONSource(const std::string& id, const V& value) const { auto dataValue = objectMember(value, "data"); if (!dataValue) { return Error{ "GeoJSON source must have a data value" }; } GeoJSONOptions options; const auto maxzoomValue = objectMember(value, "maxzoom"); if (maxzoomValue) { if (toNumber(*maxzoomValue)) { options.maxzoom = static_cast(*toNumber(*maxzoomValue)); } else { return Error{ "GeoJSON source maxzoom value must be a number" }; } } const auto bufferValue = objectMember(value, "buffer"); if (bufferValue) { if (toNumber(*bufferValue)) { options.buffer = static_cast(*toNumber(*bufferValue)); } else { return Error{ "GeoJSON source buffer value must be a number" }; } } const auto toleranceValue = objectMember(value, "tolerance"); if (toleranceValue) { if (toNumber(*toleranceValue)) { options.tolerance = static_cast(*toNumber(*toleranceValue)); } else { return Error{ "GeoJSON source tolerance value must be a number" }; } } const auto clusterValue = objectMember(value, "cluster"); if (clusterValue) { if (toBool(*clusterValue)) { options.cluster = *toBool(*clusterValue); } else { return Error{ "GeoJSON source cluster value must be a boolean" }; } } const auto clusterMaxZoomValue = objectMember(value, "clusterMaxZoom"); if (clusterMaxZoomValue) { if (toNumber(*clusterMaxZoomValue)) { options.clusterMaxZoom = static_cast(*toNumber(*clusterMaxZoomValue)); } else { return Error{ "GeoJSON source clusterMaxZoom value must be a number" }; } } const auto clusterRadiusValue = objectMember(value, "clusterRadius"); if (clusterRadiusValue) { if (toNumber(*clusterRadiusValue)) { options.clusterRadius = static_cast(*toNumber(*clusterRadiusValue)); } else { return Error{ "GeoJSON source clusterRadius value must be a number" }; } } auto result = std::make_unique(id, options); if (isObject(*dataValue)) { Result geoJSON = convertGeoJSON(*dataValue); if (!geoJSON) { return geoJSON.error(); } result->setGeoJSON(std::move(*geoJSON)); } else if (toString(*dataValue)) { result->setURL(*toString(*dataValue)); } else { return Error{ "GeoJSON data must be a URL or an object" }; } return std::move(result); } }; } // namespace conversion } // namespace style } // namespace mbgl