#include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { // A tile source can either specify a URL to TileJSON, or inline TileJSON. static optional> convertURLOrTileset(const Convertible& value, Error& error) { auto urlVal = objectMember(value, "url"); if (!urlVal) { optional tileset = convert(value, error); if (!tileset) { return nullopt; } return { *tileset }; } optional url = toString(*urlVal); if (!url) { error.message = "source url must be a string"; return nullopt; } return { *url }; } static optional> convertRasterSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return nullopt; } 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.message = "invalid tileSize"; return nullopt; } tileSize = *size; } return { std::make_unique(id, std::move(*urlOrTileset), tileSize) }; } static optional> convertRasterDEMSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return nullopt; } 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.message = "invalid tileSize"; return nullopt; } tileSize = *size; } return { std::make_unique(id, std::move(*urlOrTileset), tileSize) }; } static optional> convertVectorSource(const std::string& id, const Convertible& value, Error& error) { optional> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { return nullopt; } return { std::make_unique(id, std::move(*urlOrTileset)) }; } static optional> convertGeoJSONSource(const std::string& id, const Convertible& value, Error& error) { auto dataValue = objectMember(value, "data"); if (!dataValue) { error.message = "GeoJSON source must have a data value"; return nullopt; } optional options = convert(value, error); if (!options) { return nullopt; } auto result = std::make_unique(id, *options); if (isObject(*dataValue)) { optional geoJSON = convert(*dataValue, error); if (!geoJSON) { return nullopt; } result->setGeoJSON(std::move(*geoJSON)); } else if (toString(*dataValue)) { result->setURL(*toString(*dataValue)); } else { error.message = "GeoJSON data must be a URL or an object"; return nullopt; } return { std::move(result) }; } static optional> convertImageSource(const std::string& id, const Convertible& value, Error& error) { auto urlValue = objectMember(value, "url"); if (!urlValue) { error.message = "Image source must have a url value"; return nullopt; } auto urlString = toString(*urlValue); if (!urlString) { error.message = "Image url must be a URL string"; return nullopt; } auto coordinatesValue = objectMember(value, "coordinates"); if (!coordinatesValue) { error.message = "Image source must have a coordinates values"; return nullopt; } if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) { error.message = "Image coordinates must be an array of four longitude latitude pairs"; return nullopt; } std::array coordinates; for (std::size_t i=0; i < 4; i++) { auto latLng = conversion::convert(arrayMember(*coordinatesValue,i), error); if (!latLng) { return nullopt; } coordinates[i] = *latLng; } auto result = std::make_unique(id, coordinates); result->setURL(*urlString); return { std::move(result) }; } optional> Converter>::operator()(const Convertible& value, Error& error, const std::string& id) const { if (!isObject(value)) { error.message = "source must be an object"; return nullopt; } auto typeValue = objectMember(value, "type"); if (!typeValue) { error.message = "source must have a type"; return nullopt; } optional type = toString(*typeValue); if (!type) { error.message = "source type must be a string"; return nullopt; } const std::string tname = *type; if (*type == "raster") { return convertRasterSource(id, value, error); } else if (*type == "raster-dem") { return convertRasterDEMSource(id, value, error); } else if (*type == "vector") { return convertVectorSource(id, value, error); } else if (*type == "geojson") { return convertGeoJSONSource(id, value, error); } else if (*type == "image") { return convertImageSource(id, value, error); } else { error.message = "invalid source type"; return nullopt; } } } // namespace conversion } // namespace style } // namespace mbgl