diff options
Diffstat (limited to 'include/mbgl/style/conversion')
-rw-r--r-- | include/mbgl/style/conversion/geojson.hpp | 15 | ||||
-rw-r--r-- | include/mbgl/style/conversion/source.hpp | 123 | ||||
-rw-r--r-- | include/mbgl/style/conversion/tileset.hpp | 67 |
3 files changed, 205 insertions, 0 deletions
diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp new file mode 100644 index 0000000000..ba10b3ecc8 --- /dev/null +++ b/include/mbgl/style/conversion/geojson.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/sources/geojson_source.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template <class V> +Result<GeoJSON> convertGeoJSON(const V& value); + +} // namespace conversion +} // namespace style +} // namespace mbgl diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp new file mode 100644 index 0000000000..00c6afb9fe --- /dev/null +++ b/include/mbgl/style/conversion/source.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include <mbgl/style/source.hpp> +#include <mbgl/style/sources/geojson_source.hpp> +#include <mbgl/style/sources/raster_source.hpp> +#include <mbgl/style/sources/vector_source.hpp> +#include <mbgl/style/conversion.hpp> +#include <mbgl/style/conversion/tileset.hpp> +#include <mbgl/style/conversion/geojson.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter<std::unique_ptr<Source>> { +public: + template <class V> + Result<std::unique_ptr<Source>> 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<std::string> 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 <class V> + Result<variant<std::string, Tileset>> convertURLOrTileset(const V& value) const { + auto urlVal = objectMember(value, "url"); + if (!urlVal) { + Result<Tileset> tileset = convert<Tileset>(value); + if (!tileset) { + return tileset.error(); + } + return *tileset; + } + + optional<std::string> url = toString(*urlVal); + if (!url) { + return Error { "source url must be a string" }; + } + + return *url; + } + + template <class V> + Result<std::unique_ptr<Source>> convertRasterSource(const std::string& id, const V& value) const { + Result<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + uint16_t tileSize = util::tileSize; + auto tileSizeValue = objectMember(value, "tileSize"); + if (tileSizeValue) { + optional<float> size = toNumber(*tileSizeValue); + if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) { + return Error { "invalid tileSize" }; + } + tileSize = *size; + } + + return std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize); + } + + template <class V> + Result<std::unique_ptr<Source>> convertVectorSource(const std::string& id, const V& value) const { + Result<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value); + if (!urlOrTileset) { + return urlOrTileset.error(); + } + + return std::make_unique<VectorSource>(id, std::move(*urlOrTileset)); + } + + template <class V> + Result<std::unique_ptr<Source>> 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<GeoJSONSource>(id); + + if (isObject(*dataValue)) { + Result<GeoJSON> 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 diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp new file mode 100644 index 0000000000..46425597af --- /dev/null +++ b/include/mbgl/style/conversion/tileset.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include <mbgl/util/tileset.hpp> +#include <mbgl/style/conversion.hpp> + +namespace mbgl { +namespace style { +namespace conversion { + +template <> +struct Converter<Tileset> { +public: + template <class V> + Result<Tileset> operator()(const V& value) const { + Tileset result; + + auto tiles = objectMember(value, "tiles"); + if (!tiles) { + return Error { "source must have tiles" }; + } + + if (!isArray(*tiles)) { + return Error { "source tiles must be an array" }; + } + + for (std::size_t i = 0; i < arrayLength(*tiles); i++) { + optional<std::string> urlTemplate = toString(arrayMember(*tiles, i)); + if (!urlTemplate) { + return Error { "source tiles member must be a string" }; + } + result.tiles.push_back(std::move(*urlTemplate)); + } + + auto minzoomValue = objectMember(value, "minzoom"); + if (minzoomValue) { + optional<float> minzoom = toNumber(*minzoomValue); + if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) { + return Error { "invalid minzoom" }; + } + result.zoomRange.min = *minzoom; + } + + auto maxzoomValue = objectMember(value, "maxzoom"); + if (maxzoomValue) { + optional<float> maxzoom = toNumber(*maxzoomValue); + if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) { + return Error { "invalid maxzoom" }; + } + result.zoomRange.max = *maxzoom; + } + + auto attributionValue = objectMember(value, "attribution"); + if (attributionValue) { + optional<std::string> attribution = toString(*attributionValue); + if (!attribution) { + return Error { "source attribution must be a string" }; + } + result.attribution = std::move(*attribution); + } + + return result; + } +}; + +} // namespace conversion +} // namespace style +} // namespace mbgl |