#pragma once #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { template <> struct Converter> { public: template optional> operator()(const V& value, Error& error, const std::string& id) const { if (!isObject(value)) { error = { "source must be an object" }; return {}; } auto typeValue = objectMember(value, "type"); if (!typeValue) { error = { "source must have a type" }; return {}; } optional type = toString(*typeValue); if (!type) { error = { "source type must be a string" }; return {}; } if (*type == "raster") { return convertRasterSource(id, value, error); } else if (*type == "vector") { return convertVectorSource(id, value, error); } else if (*type == "geojson") { return convertGeoJSONSource(id, value, error); } else { error = { "invalid source type" }; return {}; } } private: // A tile source can either specify a URL to TileJSON, or inline TileJSON. template optional> convertURLOrTileset(const V& value, Error& error) const { auto urlVal = objectMember(value, "url"); if (!urlVal) { optional tileset = convert(value, error); if (!tileset) { return {}; } return { *tileset }; } optional url = toString(*urlVal); if (!url) { error = { "source url must be a string" }; return {}; } return { *url }; } template optional> convertRasterSource(const std::string& id, const V& value, Error& error) const { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return {}; } 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()) { error = { "invalid tileSize" }; return {}; } tileSize = *size; } return { std::make_unique(id, std::move(*urlOrTileset), tileSize) }; } template optional> convertVectorSource(const std::string& id, const V& value, Error& error) const { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return {}; } return { std::make_unique(id, std::move(*urlOrTileset)) }; } template optional> convertGeoJSONSource(const std::string& id, const V& value, Error& error) const { auto dataValue = objectMember(value, "data"); if (!dataValue) { error = { "GeoJSON source must have a data value" }; return {}; } optional options = convert(value, error); if (!options) { return {}; } auto result = std::make_unique(id, *options); if (isObject(*dataValue)) { optional geoJSON = convert(*dataValue, error); if (!geoJSON) { return {}; } result->setGeoJSON(std::move(*geoJSON)); } else if (toString(*dataValue)) { result->setURL(*toString(*dataValue)); } else { error = { "GeoJSON data must be a URL or an object" }; return {}; } return { std::move(result) }; } }; } // namespace conversion } // namespace style } // namespace mbgl