#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" }; } auto result = std::make_unique(id); 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