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 schemeValue = objectMember(value, "scheme");
        if (schemeValue) {
            optional<std::string> scheme = toString(*schemeValue);
            if (scheme && *scheme == "tms") {
                result.scheme = Tileset::Scheme::TMS;
            }
        }

        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;
    }
Exemple #2
0
    Result<Function<T>> operator()(const V& value) const {
        if (!isObject(value)) {
            return Error { "function must be an object" };
        }

        auto stopsValue = objectMember(value, "stops");
        if (!stopsValue) {
            return Error { "function value must specify stops" };
        }

        if (!isArray(*stopsValue)) {
            return Error { "function stops must be an array" };
        }

        if (arrayLength(*stopsValue) == 0) {
            return Error { "function must have at least one stop" };
        }

        std::vector<std::pair<float, T>> stops;
        for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
            const auto& stopValue = arrayMember(*stopsValue, i);

            if (!isArray(stopValue)) {
                return Error { "function stop must be an array" };
            }

            if (arrayLength(stopValue) != 2) {
                return Error { "function stop must have two elements" };
            }

            optional<float> z = toNumber(arrayMember(stopValue, 0));
            if (!z) {
                return Error { "function stop zoom level must be a number" };
            }

            Result<T> v = convert<T>(arrayMember(stopValue, 1));
            if (!v) {
                return v.error();
            }

            stops.emplace_back(*z, *v);
        }

        auto baseValue = objectMember(value, "base");
        if (!baseValue) {
            return Function<T>(stops, 1.0f);
        }

        optional<float> base = toNumber(*baseValue);
        if (!base) {
            return Error { "function base must be a number"};
        }

        return Function<T>(stops, *base);
    }
    optional<variant<Ts...>> operator()(const V& value, Error& error) const {
        std::string type = util::Interpolatable<T>::value ? "exponential" : "interval";

        auto typeValue = objectMember(value, "type");
        if (typeValue && toString(*typeValue)) {
            type = *toString(*typeValue);
        }

        bool matched = false;
        optional<variant<Ts...>> result;

        // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
        auto tryConvert = [&] (auto* tp) {
            using Stops = std::decay_t<decltype(*tp)>;
            if (type == Converter<Stops>::type) {
                matched = true;
                optional<Stops> stops = convert<Stops>(value, error);
                if (stops) {
                    result = variant<Ts...>(*stops);
                }
            }
        };

        util::ignore({
            (tryConvert((Ts*)nullptr), 0)...
        });

        if (!matched) {
            error = { "unsupported function type" };
            return {};
        }

        return result;
    }
optional<std::unique_ptr<Source>> Converter<std::unique_ptr<Source>>::operator()(const Convertible& 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<std::string> 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 if (*type == "image") {
        return convertImageSource(id, value, error);
    } else {
        error = { "invalid source type" };
        return {};
    }
}
static optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id,
                                                              const Convertible& value,
                                                              Error& error) {
    auto dataValue = objectMember(value, "data");
    if (!dataValue) {
        error = { "GeoJSON source must have a data value" };
        return {};
    }

    optional<GeoJSONOptions> options = convert<GeoJSONOptions>(value, error);
    if (!options) {
        return {};
    }

    auto result = std::make_unique<GeoJSONSource>(id, *options);

    if (isObject(*dataValue)) {
        optional<GeoJSON> geoJSON = convert<GeoJSON>(*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) };
}
Exemple #6
0
optional<Error> setPaintProperties(Layer& layer, const V& value) {
    auto paintValue = objectMember(value, "paint");
    if (!paintValue) {
        return {};
    }
    return eachMember(*paintValue, [&] (const std::string& k, const V& v) {
        return setPaintProperty(layer, k, v);
    });
}
Exemple #7
0
optional<Error> setPaintProperties(Layer& layer, const Convertible& value) {
    auto paintValue = objectMember(value, "paint");
    if (!paintValue) {
        return nullopt;
    }
    if (!isObject(*paintValue)) {
        return { { "paint must be an object" } };
    }
    return eachMember(*paintValue, [&] (const std::string& k, const Convertible& v) {
        return layer.setPaintProperty(k, v);
    });
}
static optional<std::unique_ptr<Source>> convertImageSource(const std::string& id,
                                                            const Convertible& value,
                                                            Error& error) {
    auto urlValue = objectMember(value, "url");
    if (!urlValue) {
        error = { "Image source must have a url value" };
        return {};
    }
    
    auto urlString = toString(*urlValue);
    if (!urlString) {
        error = { "Image url must be a URL string" };
        return {};
    }
    
    auto coordinatesValue = objectMember(value, "coordinates");
    if (!coordinatesValue) {
        error = { "Image source must have a coordinates values" };
        return {};
    }
    
    if (!isArray(*coordinatesValue) || arrayLength(*coordinatesValue) != 4) {
        error = { "Image coordinates must be an array of four longitude latitude pairs" };
        return {};
    }
    
    std::array<LatLng, 4> coordinates;
    for (std::size_t i=0; i < 4; i++) {
        auto latLng = conversion::convert<LatLng>(arrayMember(*coordinatesValue,i), error);
        if (!latLng) {
            return {};
        }
        coordinates[i] = *latLng;
    }
    auto result = std::make_unique<ImageSource>(id, coordinates);
    result->setURL(*urlString);

    return { std::move(result) };
}
Exemple #9
0
    optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value, Error& error) const {
        auto sourceValue = objectMember(value, "source");
        if (!sourceValue) {
            error = { "layer must have a source" };
            return {};
        }

        optional<std::string> source = toString(*sourceValue);
        if (!source) {
            error = { "layer source must be a string" };
            return {};
        }

        std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source);

        auto sourceLayerValue = objectMember(value, "source-layer");
        if (sourceLayerValue) {
            optional<std::string> sourceLayer = toString(*sourceLayerValue);
            if (!sourceLayer) {
                error = { "layer source-layer must be a string" };
                return {};
            }
            layer->setSourceLayer(*sourceLayer);
        }

        auto filterValue = objectMember(value, "filter");
        if (filterValue) {
            optional<Filter> filter = convert<Filter>(*filterValue, error);
            if (!filter) {
                return {};
            }
            layer->setFilter(*filter);
        }

        return { std::move(layer) };
    }
Exemple #10
0
    optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value, Error& error) const {
        auto sourceValue = objectMember(value, "source");
        if (!sourceValue) {
            error = { "layer must have a source" };
            return {};
        }

        optional<std::string> source = toString(*sourceValue);
        if (!source) {
            error = { "layer source must be a string" };
            return {};
        }

        return { std::make_unique<RasterLayer>(id, *source) };
    }
optional<std::map<D, R>> convertStops(const V& value, Error& error) {
    auto stopsValue = objectMember(value, "stops");
    if (!stopsValue) {
        error = { "function value must specify stops" };
        return {};
    }

    if (!isArray(*stopsValue)) {
        error = { "function stops must be an array" };
        return {};
    }

    if (arrayLength(*stopsValue) == 0) {
        error = { "function must have at least one stop" };
        return {};
    }

    std::map<D, R> stops;
    for (std::size_t i = 0; i < arrayLength(*stopsValue); ++i) {
        const auto& stopValue = arrayMember(*stopsValue, i);

        if (!isArray(stopValue)) {
            error = { "function stop must be an array" };
            return {};
        }

        if (arrayLength(stopValue) != 2) {
            error = { "function stop must have two elements" };
            return {};
        }

        optional<D> d = convert<D>(arrayMember(stopValue, 0), error);
        if (!d) {
            return {};
        }

        optional<R> r = convert<R>(arrayMember(stopValue, 1), error);
        if (!r) {
            return {};
        }

        stops.emplace(*d, *r);
    }

    return stops;
}
Exemple #12
0
// A tile source can either specify a URL to TileJSON, or inline TileJSON.
static optional<variant<std::string, Tileset>> convertURLOrTileset(const Convertible& value, Error& error) {
    auto urlVal = objectMember(value, "url");
    if (!urlVal) {
        optional<Tileset> tileset = convert<Tileset>(value, error);
        if (!tileset) {
            return {};
        }
        return { *tileset };
    }

    optional<std::string> url = toString(*urlVal);
    if (!url) {
        error = { "source url must be a string" };
        return {};
    }

    return { *url };
}
    optional<ExponentialStops<T>> operator()(const V& value, Error& error) const {
        auto stops = convertStops<float, T>(value, error);
        if (!stops) {
            return {};
        }

        auto baseValue = objectMember(value, "base");
        if (!baseValue) {
            return ExponentialStops<T>(*stops);
        }

        optional<float> base = toNumber(*baseValue);
        if (!base) {
            error = { "function base must be a number"};
            return {};
        }

        return ExponentialStops<T>(*stops, *base);
    }
Exemple #14
0
static optional<std::unique_ptr<Source>> convertRasterSource(const std::string& id,
                                                             const Convertible& value,
                                                             Error& error) {
    optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error);
    if (!urlOrTileset) {
        return {};
    }

    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()) {
            error = { "invalid tileSize" };
            return {};
        }
        tileSize = *size;
    }

    return { std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize) };
}
optional<optional<T>> convertDefaultValue(const V& value, Error& error) {
    auto defaultValueValue = objectMember(value, "default");
    if (!defaultValueValue) {
        return optional<T>();
    }

    auto defaultValue = convert<T>(*defaultValueValue, error);
    if (!defaultValue) {
        error = { R"(wrong type for "default": )" + error.message };
        return {};
    }

    return { *defaultValue };
}

template <class T>
struct Converter<SourceFunction<T>> {
    template <class V>
    optional<SourceFunction<T>> operator()(const V& value, Error& error) const {
        if (!isObject(value)) {
            error = { "function must be an object" };
            return {};
        }
optional<PropertyExpression<T>> convertFunctionToExpression(const Convertible& value, Error& error, bool convertTokens) {
    auto expression = convertFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error, convertTokens);
    if (!expression) {
        return nullopt;
    }

    optional<T> defaultValue{};

    auto defaultValueValue = objectMember(value, "default");
    if (defaultValueValue) {
        defaultValue = convert<T>(*defaultValueValue, error);
        if (!defaultValue) {
            error.message = R"(wrong type for "default": )" + error.message;
            return nullopt;
        }
    }

    return PropertyExpression<T>(std::move(*expression), defaultValue);
}

template optional<PropertyExpression<AlignmentType>>
    convertFunctionToExpression<AlignmentType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<bool>>
    convertFunctionToExpression<bool>(const Convertible&, Error&, bool);
template optional<PropertyExpression<CirclePitchScaleType>>
    convertFunctionToExpression<CirclePitchScaleType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<float>>
    convertFunctionToExpression<float>(const Convertible&, Error&, bool);
template optional<PropertyExpression<HillshadeIlluminationAnchorType>>
    convertFunctionToExpression<HillshadeIlluminationAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<IconTextFitType>>
    convertFunctionToExpression<IconTextFitType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LightAnchorType>>
    convertFunctionToExpression<LightAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LineCapType>>
    convertFunctionToExpression<LineCapType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LineJoinType>>
    convertFunctionToExpression<LineJoinType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Color>>
    convertFunctionToExpression<Color>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Position>>
    convertFunctionToExpression<Position>(const Convertible&, Error&, bool);
template optional<PropertyExpression<RasterResamplingType>>
    convertFunctionToExpression<RasterResamplingType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::array<float, 2>>>
    convertFunctionToExpression<std::array<float, 2>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::array<float, 4>>>
    convertFunctionToExpression<std::array<float, 4>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::string>>
    convertFunctionToExpression<std::string>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<float>>>
    convertFunctionToExpression<std::vector<float>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<std::string>>>
    convertFunctionToExpression<std::vector<std::string>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolAnchorType>>
    convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolPlacementType>>
    convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolZOrderType>>
    convertFunctionToExpression<SymbolZOrderType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextJustifyType>>
    convertFunctionToExpression<TextJustifyType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextTransformType>>
    convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TranslateAnchorType>>
    convertFunctionToExpression<TranslateAnchorType>(const Convertible&, Error&, bool);
    
template optional<PropertyExpression<Formatted>>
    convertFunctionToExpression<Formatted>(const Convertible&, Error&, bool);

// Ad-hoc Converters for double and int64_t. We should replace float with double wholesale,
// and promote the int64_t Converter to general use (and it should check that the input is
// an integer).
template <>
struct Converter<double> {
    optional<double> operator()(const Convertible& value, Error& error) const {
        auto converted = convert<float>(value, error);
        if (!converted) {
            return nullopt;
        }
        return *converted;
    }
};

template <>
struct Converter<int64_t> {
    optional<int64_t> operator()(const Convertible& value, Error& error) const {
        auto converted = convert<float>(value, error);
        if (!converted) {
            return nullopt;
        }
        return *converted;
    }
};

enum class FunctionType {
    Interval,
    Exponential,
    Categorical,
    Identity,
    Invalid
};

static bool interpolatable(type::Type type) {
    return type.match(
        [&] (const type::NumberType&) {
            return true;
        },
        [&] (const type::ColorType&) {
            return true;
        },
        [&] (const type::Array& array) {
            return array.N && array.itemType == type::Number;
        },
        [&] (const auto&) {
            return false;
        }
    );
}

static optional<std::unique_ptr<Expression>> convertLiteral(type::Type type, const Convertible& value, Error& error, bool convertTokens = false) {
    return type.match(
        [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
            auto result = convert<float>(value, error);
            if (!result) {
                return nullopt;
            }
            return literal(double(*result));
        },
        [&] (const type::BooleanType&) -> optional<std::unique_ptr<Expression>> {
            auto result = convert<bool>(value, error);
            if (!result) {
                return nullopt;
            }
            return literal(*result);
        },
        [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
            auto result = convert<std::string>(value, error);
            if (!result) {
                return nullopt;
            }
            return convertTokens ? convertTokenStringToExpression(*result) : literal(*result);
        },
        [&] (const type::ColorType&) -> optional<std::unique_ptr<Expression>> {
            auto result = convert<Color>(value, error);
            if (!result) {
                return nullopt;
            }
            return literal(*result);
        },
        [&] (const type::Array& array) -> optional<std::unique_ptr<Expression>> {
            if (!isArray(value)) {
                error.message = "value must be an array";
                return nullopt;
            }
            if (array.N && arrayLength(value) != *array.N) {
                error.message = "value must be an array of length " + util::toString(*array.N);
                return nullopt;
            }
            return array.itemType.match(
                [&] (const type::NumberType&) -> optional<std::unique_ptr<Expression>> {
                    std::vector<expression::Value> result;
                    result.reserve(arrayLength(value));
                    for (std::size_t i = 0; i < arrayLength(value); ++i) {
                        optional<float> number = toNumber(arrayMember(value, i));
                        if (!number) {
                            error.message = "value must be an array of numbers";
                            return nullopt;
                        }
                        result.push_back(double(*number));
                    }
                    return literal(result);
                },
                [&] (const type::StringType&) -> optional<std::unique_ptr<Expression>> {
                    std::vector<expression::Value> result;
                    result.reserve(arrayLength(value));
                    for (std::size_t i = 0; i < arrayLength(value); ++i) {
                        optional<std::string> string = toString(arrayMember(value, i));
                        if (!string) {
                            error.message = "value must be an array of strings";
                            return nullopt;
                        }
                        result.push_back(*string);
                    }
                    return literal(result);
                },
                [&] (const auto&) -> optional<std::unique_ptr<Expression>> {
                    assert(false); // No properties use this type.
                    return nullopt;
                }
            );
        },
Exemple #17
0
optional<std::unique_ptr<Layer>> Converter<std::unique_ptr<Layer>>::operator()(const Convertible& value, Error& error) const {
    if (!isObject(value)) {
        error.message = "layer must be an object";
        return nullopt;
    }

    auto idValue = objectMember(value, "id");
    if (!idValue) {
        error.message = "layer must have an id";
        return nullopt;
    }

    optional<std::string> id = toString(*idValue);
    if (!id) {
        error.message = "layer id must be a string";
        return nullopt;
    }

    auto typeValue = objectMember(value, "type");
    if (!typeValue) {
        error.message = "layer must have a type";
        return nullopt;
    }

    optional<std::string> type = toString(*typeValue);
    if (!type) {
        error.message = "layer type must be a string";
        return nullopt;
    }

    std::unique_ptr<Layer> layer = LayerManager::get()->createLayer(*type, *id, value, error);
    if (!layer) {
        return nullopt;
    }

    auto minzoomValue = objectMember(value, "minzoom");
    if (minzoomValue) {
        optional<float> minzoom = toNumber(*minzoomValue);
        if (!minzoom) {
            error.message = "minzoom must be numeric";
            return nullopt;
        }
        layer->setMinZoom(*minzoom);
    }

    auto maxzoomValue = objectMember(value, "maxzoom");
    if (maxzoomValue) {
        optional<float> maxzoom = toNumber(*maxzoomValue);
        if (!maxzoom) {
            error.message = "maxzoom must be numeric";
            return nullopt;
        }
        layer->setMaxZoom(*maxzoom);
    }

    auto layoutValue = objectMember(value, "layout");
    if (layoutValue) {
        if (!isObject(*layoutValue)) {
            error.message = "layout must be an object";
            return nullopt;
        }
        optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const Convertible& v) {
            return layer->setLayoutProperty(k, v);
        });
        if (error_) {
            error = *error_;
            return nullopt;
        }
    }

    optional<Error> error_ = setPaintProperties(*layer, value);
    if (error_) {
        error = *error_;
        return nullopt;
    }

    return std::move(layer);
}
        return {};
    }

    return { *defaultValue };
}

template <class T>
struct Converter<SourceFunction<T>> {
    template <class V>
    optional<SourceFunction<T>> operator()(const V& value, Error& error) const {
        if (!isObject(value)) {
            error = { "function must be an object" };
            return {};
        }

        auto propertyValue = objectMember(value, "property");
        if (!propertyValue) {
            error = { "function must specify property" };
            return {};
        }

        auto propertyString = toString(*propertyValue);
        if (!propertyString) {
            error = { "function property must be a string" };
            return {};
        }

        auto stops = StopsConverter<T, typename SourceFunction<T>::Stops>()(value, error);
        if (!stops) {
            return {};
        }
Exemple #19
0
    optional<std::unique_ptr<Layer>> operator()(const V& value, Error& error) const {
        if (!isObject(value)) {
            error = { "layer must be an object" };
            return {};
        }

        auto idValue = objectMember(value, "id");
        if (!idValue) {
            error = { "layer must have an id" };
            return {};
        }

        optional<std::string> id = toString(*idValue);
        if (!id) {
            error = { "layer id must be a string" };
            return {};
        }

        auto typeValue = objectMember(value, "type");
        if (!typeValue) {
            error = { "layer must have a type" };
            return {};
        }

        optional<std::string> type = toString(*typeValue);
        if (!type) {
            error = { "layer type must be a string" };
            return {};
        }

        optional<std::unique_ptr<Layer>> converted;

        if (*type == "fill") {
            converted = convertVectorLayer<FillLayer>(*id, value, error);
        } else if (*type == "fill-extrusion") {
            converted = convertVectorLayer<FillExtrusionLayer>(*id, value, error);
        } else if (*type == "line") {
            converted = convertVectorLayer<LineLayer>(*id, value, error);
        } else if (*type == "circle") {
            converted = convertVectorLayer<CircleLayer>(*id, value, error);
        } else if (*type == "symbol") {
            converted = convertVectorLayer<SymbolLayer>(*id, value, error);
        } else if (*type == "raster") {
            converted = convertRasterLayer(*id, value, error);
        } else if (*type == "background") {
            converted = convertBackgroundLayer(*id, value, error);
        } else {
            error = { "invalid layer type" };
            return {};
        }

        if (!converted) {
            return converted;
        }

        std::unique_ptr<Layer> layer = std::move(*converted);

        auto minzoomValue = objectMember(value, "minzoom");
        if (minzoomValue) {
            optional<float> minzoom = toNumber(*minzoomValue);
            if (!minzoom) {
                error = { "minzoom must be numeric" };
                return {};
            }
            layer->setMinZoom(*minzoom);
        }

        auto maxzoomValue = objectMember(value, "maxzoom");
        if (maxzoomValue) {
            optional<float> maxzoom = toNumber(*maxzoomValue);
            if (!maxzoom) {
                error = { "maxzoom must be numeric" };
                return {};
            }
            layer->setMaxZoom(*maxzoom);
        }

        auto layoutValue = objectMember(value, "layout");
        if (layoutValue) {
            if (!isObject(*layoutValue)) {
                error = { "layout must be an object" };
                return {};
            }
            optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const V& v) {
                return setLayoutProperty(*layer, k, v);
            });
            if (error_) {
                error = *error_;
                return {};
            }
        }

        optional<Error> error_ = setPaintProperties(*layer, value);
        if (error_) {
            error = *error_;
            return {};
        }

        return std::move(layer);
    }
Exemple #20
0
optional<Light> Converter<Light>::operator()(const Convertible& value, Error& error) const {
    if (!isObject(value)) {
        error.message = "light must be an object";
        return nullopt;
    }

    Light light;

    const auto anchor = objectMember(value, "anchor");
    if (anchor) {
        optional<PropertyValue<LightAnchorType>> convertedAnchor =
            convert<PropertyValue<LightAnchorType>>(*anchor, error, false, false);

        if (convertedAnchor) {
            light.setAnchor(*convertedAnchor);
        } else {
            return nullopt;
        }
    }

    const auto anchorTransition = objectMember(value, "anchor-transition");
    if (anchorTransition) {
        optional<TransitionOptions> transition =
            convert<TransitionOptions>(*anchorTransition, error);
        if (transition) {
            light.setAnchorTransition(*transition);
        } else {
            return nullopt;
        }
    }

    const auto color = objectMember(value, "color");
    if (color) {
        optional<PropertyValue<Color>> convertedColor =
            convert<PropertyValue<Color>>(*color, error, false, false);

        if (convertedColor) {
            light.setColor(*convertedColor);
        } else {
            return nullopt;
        }
    }

    const auto colorTransition = objectMember(value, "color-transition");
    if (colorTransition) {
        optional<TransitionOptions> transition =
            convert<TransitionOptions>(*colorTransition, error);
        if (transition) {
            light.setColorTransition(*transition);
        } else {
            return nullopt;
        }
    }

    const auto position = objectMember(value, "position");
    if (position) {
        optional<PropertyValue<Position>> convertedPosition =
            convert<PropertyValue<Position>>(*position, error, false, false);

        if (convertedPosition) {
            light.setPosition(*convertedPosition);
        } else {
            return nullopt;
        }
    }

    const auto positionTransition = objectMember(value, "position-transition");
    if (positionTransition) {
        optional<TransitionOptions> transition =
            convert<TransitionOptions>(*positionTransition, error);
        if (transition) {
            light.setPositionTransition(*transition);
        } else {
            return nullopt;
        }
    }

    const auto intensity = objectMember(value, "intensity");
    if (intensity) {
        optional<PropertyValue<float>> convertedIntensity =
            convert<PropertyValue<float>>(*intensity, error, false, false);

        if (convertedIntensity) {
            light.setIntensity(*convertedIntensity);
        } else {
            return nullopt;
        }
    }

    const auto intensityTransition = objectMember(value, "intensity-transition");
    if (intensityTransition) {
        optional<TransitionOptions> transition =
            convert<TransitionOptions>(*intensityTransition, error);
        if (transition) {
            light.setIntensityTransition(*transition);
        } else {
            return nullopt;
        }
    }

    return { std::move(light) };
}