#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { template optional setLayoutProperty(Layer& layer, const std::string& name, const V& value) { static const auto setters = makeLayoutPropertySetters(); auto it = setters.find(name); if (it == setters.end()) { return Error { "property not found" }; } return it->second(layer, value); } template optional setPaintProperty(Layer& layer, const std::string& name, const V& value, const optional& klass) { static const auto setters = makePaintPropertySetters(); auto it = setters.find(name); if (it == setters.end()) { return Error { "property not found" }; } return it->second(layer, value, klass); } template optional setPaintProperties(Layer& layer, const V& value) { return eachMember(value, [&] (const std::string& paintName, const V& paintValue) -> optional { if (paintName.compare(0, 5, "paint") != 0) { return {}; } optional klass; if (paintName.compare(0, 6, "paint.") == 0) { klass = paintName.substr(6); } return eachMember(paintValue, [&] (const std::string& k, const V& v) { return setPaintProperty(layer, k, v, klass); }); }); } template <> struct Converter> { public: template Result> operator()(const V& value) const { if (!isObject(value)) { return Error { "layer must be an object" }; } auto idValue = objectMember(value, "id"); if (!idValue) { return Error { "layer must have an id" }; } optional id = toString(*idValue); if (!id) { return Error { "layer id must be a string" }; } auto typeValue = objectMember(value, "type"); if (!typeValue) { return Error { "layer must have a type" }; } optional type = toString(*typeValue); if (!type) { return Error { "layer type must be a string" }; } Result> converted; if (*type == "fill") { converted = convertVectorLayer(*id, value); } else if (*type == "line") { converted = convertVectorLayer(*id, value); } else if (*type == "circle") { converted = convertVectorLayer(*id, value); } else if (*type == "symbol") { converted = convertVectorLayer(*id, value); } else if (*type == "raster") { converted = convertRasterLayer(*id, value); } else if (*type == "background") { converted = convertBackgroundLayer(*id, value); } else { return Error { "invalid layer type" }; } if (!converted) { return converted; } std::unique_ptr layer = std::move(*converted); auto minzoomValue = objectMember(value, "minzoom"); if (minzoomValue) { optional minzoom = toNumber(*minzoomValue); if (!minzoom) { return Error { "minzoom must be numeric" }; } layer->setMinZoom(*minzoom); } auto maxzoomValue = objectMember(value, "maxzoom"); if (maxzoomValue) { optional maxzoom = toNumber(*maxzoomValue); if (!maxzoom) { return Error { "maxzoom must be numeric" }; } layer->setMaxZoom(*maxzoom); } auto layoutValue = objectMember(value, "layout"); if (layoutValue) { if (!isObject(*layoutValue)) { return Error { "layout must be an object" }; } optional error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) { return setLayoutProperty(*layer, k, v); }); if (error) { return *error; } } optional error = setPaintProperties(*layer, value); if (error) { return *error; } return std::move(layer); } private: template Result> convertVectorLayer(const std::string& id, const V& value) const { auto sourceValue = objectMember(value, "source"); if (!sourceValue) { return Error { "layer must have a source" }; } optional source = toString(*sourceValue); if (!source) { return Error { "layer source must be a string" }; } std::unique_ptr layer = std::make_unique(id, *source); auto sourceLayerValue = objectMember(value, "source-layer"); if (sourceLayerValue) { optional sourceLayer = toString(*sourceLayerValue); if (!sourceLayer) { return Error { "layer source-layer must be a string" }; } layer->setSourceLayer(*sourceLayer); } auto filterValue = objectMember(value, "filter"); if (filterValue) { Result filter = convert(*filterValue); if (!filter) { return filter.error(); } layer->setFilter(*filter); } return std::move(layer); } template Result> convertRasterLayer(const std::string& id, const V& value) const { auto sourceValue = objectMember(value, "source"); if (!sourceValue) { return Error { "layer must have a source" }; } optional source = toString(*sourceValue); if (!source) { return Error { "layer source must be a string" }; } return std::make_unique(id, *source); } template Result> convertBackgroundLayer(const std::string& id, const V&) const { return std::make_unique(id); } }; } // namespace conversion } // namespace style } // namespace mbgl