diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-03-07 17:00:53 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2017-03-23 13:31:13 -0700 |
commit | d7227e13a7a87cf50a4c8c1f0615fc565f5a2679 (patch) | |
tree | eda76a2da3220f3cfeec901400369cf9c8361f58 /include/mbgl/style | |
parent | 1c757cce34344dfecc9a724034680225143f92b7 (diff) | |
download | qtlocation-mapboxgl-d7227e13a7a87cf50a4c8c1f0615fc565f5a2679.tar.gz |
[all] Replace Result<T> with optional<T> plus out Error parameter
Diffstat (limited to 'include/mbgl/style')
-rw-r--r-- | include/mbgl/style/conversion.hpp | 39 | ||||
-rw-r--r-- | include/mbgl/style/conversion/constant.hpp | 63 | ||||
-rw-r--r-- | include/mbgl/style/conversion/data_driven_property_value.hpp | 18 | ||||
-rw-r--r-- | include/mbgl/style/conversion/filter.hpp | 157 | ||||
-rw-r--r-- | include/mbgl/style/conversion/function.hpp | 175 | ||||
-rw-r--r-- | include/mbgl/style/conversion/geojson.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/style/conversion/geojson_options.hpp | 20 | ||||
-rw-r--r-- | include/mbgl/style/conversion/layer.hpp | 88 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_setter.hpp | 20 | ||||
-rw-r--r-- | include/mbgl/style/conversion/property_value.hpp | 16 | ||||
-rw-r--r-- | include/mbgl/style/conversion/source.hpp | 79 | ||||
-rw-r--r-- | include/mbgl/style/conversion/tileset.hpp | 20 | ||||
-rw-r--r-- | include/mbgl/style/conversion/transition_options.hpp | 11 |
13 files changed, 391 insertions, 317 deletions
diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp index e53adcb942..d6fb3a6dd0 100644 --- a/include/mbgl/style/conversion.hpp +++ b/include/mbgl/style/conversion.hpp @@ -1,6 +1,6 @@ #pragma once -#include <mbgl/util/variant.hpp> +#include <mbgl/util/optional.hpp> #include <string> @@ -21,11 +21,11 @@ namespace conversion { A single template function serves as the public interface: template <class T, class V> - Result<T> convert(const V& value); + optional<T> convert(const V& value, Error& error); - Where `T` is one of the above types. If the conversion fails, the `Error` variant of `Result` is - returned, which includes diagnostic text suitable for presentation to a library user. Otherwise, - the `T` variant of `Result` is returned. + Where `T` is one of the above types. If the conversion fails, the result is empty, and the + error parameter includes diagnostic text suitable for presentation to a library user. Otherwise, + a filled optional is returned. The implementation of `convert` requires that the following are legal expressions for a value `v` of type `const V&`: @@ -57,37 +57,12 @@ namespace conversion { struct Error { std::string message; }; -template <class T> -class Result : private variant<T, Error> { -public: - using variant<T, Error>::variant; - - explicit operator bool() const { - return this->template is<T>(); - } - - T& operator*() { - assert(this->template is<T>()); - return this->template get<T>(); - } - - const T& operator*() const { - assert(this->template is<T>()); - return this->template get<T>(); - } - - const Error& error() const { - assert(this->template is<Error>()); - return this->template get<Error>(); - } -}; - template <class T, class Enable = void> struct Converter; template <class T, class V, class...Args> -Result<T> convert(const V& value, Args&&...args) { - return Converter<T>()(value, std::forward<Args>(args)...); +optional<T> convert(const V& value, Error& error, Args&&...args) { + return Converter<T>()(value, error, std::forward<Args>(args)...); } } // namespace conversion diff --git a/include/mbgl/style/conversion/constant.hpp b/include/mbgl/style/conversion/constant.hpp index 05bf968f4d..1e1fdc2ee8 100644 --- a/include/mbgl/style/conversion/constant.hpp +++ b/include/mbgl/style/conversion/constant.hpp @@ -16,10 +16,11 @@ namespace conversion { template <> struct Converter<bool> { template <class V> - Result<bool> operator()(const V& value) const { + optional<bool> operator()(const V& value, Error& error) const { optional<bool> converted = toBool(value); if (!converted) { - return Error { "value must be a boolean" }; + error = { "value must be a boolean" }; + return {}; } return *converted; } @@ -28,10 +29,11 @@ struct Converter<bool> { template <> struct Converter<float> { template <class V> - Result<float> operator()(const V& value) const { + optional<float> operator()(const V& value, Error& error) const { optional<float> converted = toNumber(value); if (!converted) { - return Error { "value must be a number" }; + error = { "value must be a number" }; + return {}; } return *converted; } @@ -40,10 +42,11 @@ struct Converter<float> { template <> struct Converter<std::string> { template <class V> - Result<std::string> operator()(const V& value) const { + optional<std::string> operator()(const V& value, Error& error) const { optional<std::string> converted = toString(value); if (!converted) { - return Error { "value must be a string" }; + error = { "value must be a string" }; + return {}; } return *converted; } @@ -52,15 +55,17 @@ struct Converter<std::string> { template <class T> struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> { template <class V> - Result<T> operator()(const V& value) const { + optional<T> operator()(const V& value, Error& error) const { optional<std::string> string = toString(value); if (!string) { - return Error { "value must be a string" }; + error = { "value must be a string" }; + return {}; } const auto result = Enum<T>::toEnum(*string); if (!result) { - return Error { "value must be a valid enumeration value" }; + error = { "value must be a valid enumeration value" }; + return {}; } return *result; @@ -70,15 +75,17 @@ struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> { template <> struct Converter<Color> { template <class V> - Result<Color> operator()(const V& value) const { + optional<Color> operator()(const V& value, Error& error) const { optional<std::string> string = toString(value); if (!string) { - return Error { "value must be a string" }; + error = { "value must be a string" }; + return {}; } optional<Color> color = Color::parse(*string); if (!color) { - return Error { "value must be a valid color" }; + error = { "value must be a valid color" }; + return {}; } return *color; @@ -88,15 +95,17 @@ struct Converter<Color> { template <> struct Converter<std::array<float, 2>> { template <class V> - Result<std::array<float, 2>> operator()(const V& value) const { + optional<std::array<float, 2>> operator()(const V& value, Error& error) const { if (!isArray(value) || arrayLength(value) != 2) { - return Error { "value must be an array of two numbers" }; + error = { "value must be an array of two numbers" }; + return {}; } optional<float> first = toNumber(arrayMember(value, 0)); optional<float> second = toNumber(arrayMember(value, 1)); if (!first || !second) { - return Error { "value must be an array of two numbers" }; + error = { "value must be an array of two numbers" }; + return {}; } return std::array<float, 2> {{ *first, *second }}; @@ -106,9 +115,10 @@ struct Converter<std::array<float, 2>> { template <> struct Converter<std::array<float, 4>> { template <class V> - Result<std::array<float, 4>> operator()(const V& value) const { + optional<std::array<float, 4>> operator()(const V& value, Error& error) const { if (!isArray(value) || arrayLength(value) != 4) { - return Error { "value must be an array of four numbers" }; + error = { "value must be an array of four numbers" }; + return {}; } optional<float> first = toNumber(arrayMember(value, 0)); @@ -116,7 +126,8 @@ struct Converter<std::array<float, 4>> { optional<float> third = toNumber(arrayMember(value, 2)); optional<float> fourth = toNumber(arrayMember(value, 3)); if (!first || !second) { - return Error { "value must be an array of four numbers" }; + error = { "value must be an array of four numbers" }; + return {}; } return std::array<float, 4> {{ *first, *second, *third, *fourth }}; @@ -126,9 +137,10 @@ struct Converter<std::array<float, 4>> { template <> struct Converter<std::vector<float>> { template <class V> - Result<std::vector<float>> operator()(const V& value) const { + optional<std::vector<float>> operator()(const V& value, Error& error) const { if (!isArray(value)) { - return Error { "value must be an array" }; + error = { "value must be an array" }; + return {}; } std::vector<float> result; @@ -137,7 +149,8 @@ struct Converter<std::vector<float>> { for (std::size_t i = 0; i < arrayLength(value); ++i) { optional<float> number = toNumber(arrayMember(value, i)); if (!number) { - return Error { "value must be an array of numbers" }; + error = { "value must be an array of numbers" }; + return {}; } result.push_back(*number); } @@ -149,9 +162,10 @@ struct Converter<std::vector<float>> { template <> struct Converter<std::vector<std::string>> { template <class V> - Result<std::vector<std::string>> operator()(const V& value) const { + optional<std::vector<std::string>> operator()(const V& value, Error& error) const { if (!isArray(value)) { - return Error { "value must be an array" }; + error = { "value must be an array" }; + return {}; } std::vector<std::string> result; @@ -160,7 +174,8 @@ struct Converter<std::vector<std::string>> { for (std::size_t i = 0; i < arrayLength(value); ++i) { optional<std::string> string = toString(arrayMember(value, i)); if (!string) { - return Error { "value must be an array of strings" }; + error = { "value must be an array of strings" }; + return {}; } result.push_back(*string); } diff --git a/include/mbgl/style/conversion/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp index 83f44fdb27..79b15dcfb0 100644 --- a/include/mbgl/style/conversion/data_driven_property_value.hpp +++ b/include/mbgl/style/conversion/data_driven_property_value.hpp @@ -12,29 +12,29 @@ namespace conversion { template <class T> struct Converter<DataDrivenPropertyValue<T>> { template <class V> - Result<DataDrivenPropertyValue<T>> operator()(const V& value) const { + optional<DataDrivenPropertyValue<T>> operator()(const V& value, Error& error) const { if (isUndefined(value)) { - return {}; + return DataDrivenPropertyValue<T>(); } else if (!isObject(value)) { - Result<T> constant = convert<T>(value); + optional<T> constant = convert<T>(value, error); if (!constant) { - return constant.error(); + return {}; } return DataDrivenPropertyValue<T>(*constant); } else if (!objectMember(value, "property")) { - Result<CameraFunction<T>> function = convert<CameraFunction<T>>(value); + optional<CameraFunction<T>> function = convert<CameraFunction<T>>(value, error); if (!function) { - return function.error(); + return {}; } return DataDrivenPropertyValue<T>(*function); } else { - Result<CompositeFunction<T>> composite = convert<CompositeFunction<T>>(value); + optional<CompositeFunction<T>> composite = convert<CompositeFunction<T>>(value, error); if (composite) { return DataDrivenPropertyValue<T>(*composite); } - Result<SourceFunction<T>> source = convert<SourceFunction<T>>(value); + optional<SourceFunction<T>> source = convert<SourceFunction<T>>(value, error); if (!source) { - return source.error(); + return {}; } return DataDrivenPropertyValue<T>(*source); } diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp index 2c4eeb4ac7..1f8f0fd161 100644 --- a/include/mbgl/style/conversion/filter.hpp +++ b/include/mbgl/style/conversion/filter.hpp @@ -12,65 +12,71 @@ template <> struct Converter<Filter> { public: template <class V> - Result<Filter> operator()(const V& value) const { + optional<Filter> operator()(const V& value, Error& error) const { if (!isArray(value)) { - return Error { "filter expression must be an array" }; + error = { "filter expression must be an array" }; + return {}; } if (arrayLength(value) < 1) { - return Error { "filter expression must have at least 1 element" }; + error = { "filter expression must have at least 1 element" }; + return {}; } optional<std::string> op = toString(arrayMember(value, 0)); if (!op) { - return Error { "filter operator must be a string" }; + error = { "filter operator must be a string" }; + return {}; } if (*op == "==") { - return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value); + return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value, error); } else if (*op == "!=") { - return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value); + return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value, error); } else if (*op == ">") { - return convertBinaryFilter<GreaterThanFilter>(value); + return convertBinaryFilter<GreaterThanFilter>(value, error); } else if (*op == ">=") { - return convertBinaryFilter<GreaterThanEqualsFilter>(value); + return convertBinaryFilter<GreaterThanEqualsFilter>(value, error); } else if (*op == "<") { - return convertBinaryFilter<LessThanFilter>(value); + return convertBinaryFilter<LessThanFilter>(value, error); } else if (*op == "<=") { - return convertBinaryFilter<LessThanEqualsFilter>(value); + return convertBinaryFilter<LessThanEqualsFilter>(value, error); } else if (*op == "in") { - return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value); + return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value, error); } else if (*op == "!in") { - return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value); + return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value, error); } else if (*op == "all") { - return convertCompoundFilter<AllFilter>(value); + return convertCompoundFilter<AllFilter>(value, error); } else if (*op == "any") { - return convertCompoundFilter<AnyFilter>(value); + return convertCompoundFilter<AnyFilter>(value, error); } else if (*op == "none") { - return convertCompoundFilter<NoneFilter>(value); + return convertCompoundFilter<NoneFilter>(value, error); } else if (*op == "has") { - return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value); + return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value, error); } else if (*op == "!has") { - return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value); + return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error); } - return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; + error = { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" }; + return {}; } private: - Result<Value> normalizeValue(const optional<Value>& value) const { + optional<Value> normalizeValue(const optional<Value>& value, Error& error) const { if (!value) { - return Error { "filter expression value must be a boolean, number, or string" }; + error = { "filter expression value must be a boolean, number, or string" }; + return {}; } else { return *value; } } template <class V> - Result<FeatureType> toFeatureType(const V& value) const { + optional<FeatureType> toFeatureType(const V& value, Error& error) const { optional<std::string> type = toString(value); if (!type) { - return Error { "value for $type filter must be a string" }; + error = { "value for $type filter must be a string" }; + return {}; } else if (*type == "Point") { return FeatureType::Point; } else if (*type == "LineString") { @@ -78,162 +84,173 @@ private: } else if (*type == "Polygon") { return FeatureType::Polygon; } else { - return Error { "value for $type filter must be Point, LineString, or Polygon" }; + error = { "value for $type filter must be Point, LineString, or Polygon" }; + return {}; } } template <class V> - Result<FeatureIdentifier> toFeatureIdentifier(const V& value) const { + optional<FeatureIdentifier> toFeatureIdentifier(const V& value, Error& error) const { optional<Value> identifier = toValue(value); if (!identifier) { - return Error { "filter expression value must be a boolean, number, or string" }; + error = { "filter expression value must be a boolean, number, or string" }; + return {}; } else { return (*identifier).match( - [] (uint64_t t) -> Result<FeatureIdentifier> { return t; }, - [] ( int64_t t) -> Result<FeatureIdentifier> { return t; }, - [] ( double t) -> Result<FeatureIdentifier> { return t; }, - [] (const std::string& t) -> Result<FeatureIdentifier> { return t; }, - [] (const auto&) -> Result<FeatureIdentifier> { - return Error { "filter expression value must be a boolean, number, or string" }; + [] (uint64_t t) -> optional<FeatureIdentifier> { return { t }; }, + [] ( int64_t t) -> optional<FeatureIdentifier> { return { t }; }, + [] ( double t) -> optional<FeatureIdentifier> { return { t }; }, + [] (const std::string& t) -> optional<FeatureIdentifier> { return { t }; }, + [&] (const auto&) -> optional<FeatureIdentifier> { + error = { "filter expression value must be a boolean, number, or string" }; + return {}; }); } } template <class FilterType, class IdentifierFilterType, class V> - Result<Filter> convertUnaryFilter(const V& value) const { + optional<Filter> convertUnaryFilter(const V& value, Error& error) const { if (arrayLength(value) < 2) { - return Error { "filter expression must have 2 elements" }; + error = { "filter expression must have 2 elements" }; + return {}; } optional<std::string> key = toString(arrayMember(value, 1)); if (!key) { - return Error { "filter expression key must be a string" }; + error = { "filter expression key must be a string" }; + return {}; } if (*key == "$id") { - return IdentifierFilterType {}; + return { IdentifierFilterType {} }; } else { - return FilterType { *key }; + return { FilterType { *key } }; } } template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V> - Result<Filter> convertEqualityFilter(const V& value) const { + optional<Filter> convertEqualityFilter(const V& value, Error& error) const { if (arrayLength(value) < 3) { - return Error { "filter expression must have 3 elements" }; + error = { "filter expression must have 3 elements" }; + return {}; } optional<std::string> key = toString(arrayMember(value, 1)); if (!key) { - return Error { "filter expression key must be a string" }; + error = { "filter expression key must be a string" }; + return {}; } if (*key == "$type") { - Result<FeatureType> filterValue = toFeatureType(arrayMember(value, 2)); + optional<FeatureType> filterValue = toFeatureType(arrayMember(value, 2), error); if (!filterValue) { - return filterValue.error(); + return {}; } - return TypeFilterType { *filterValue }; + return { TypeFilterType { *filterValue } }; } else if (*key == "$id") { - Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2)); + optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2), error); if (!filterValue) { - return filterValue.error(); + return {}; } - return IdentifierFilterType { *filterValue }; + return { IdentifierFilterType { *filterValue } }; } else { - Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2))); + optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error); if (!filterValue) { - return filterValue.error(); + return {}; } - return FilterType { *key, *filterValue }; + return { FilterType { *key, *filterValue } }; } } template <class FilterType, class V> - Result<Filter> convertBinaryFilter(const V& value) const { + optional<Filter> convertBinaryFilter(const V& value, Error& error) const { if (arrayLength(value) < 3) { - return Error { "filter expression must have 3 elements" }; + error = { "filter expression must have 3 elements" }; + return {}; } optional<std::string> key = toString(arrayMember(value, 1)); if (!key) { - return Error { "filter expression key must be a string" }; + error = { "filter expression key must be a string" }; + return {}; } - Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2))); + optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error); if (!filterValue) { - return filterValue.error(); + return {}; } - return FilterType { *key, *filterValue }; + return { FilterType { *key, *filterValue } }; } template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V> - Result<Filter> convertSetFilter(const V& value) const { + optional<Filter> convertSetFilter(const V& value, Error& error) const { if (arrayLength(value) < 2) { - return Error { "filter expression must at least 2 elements" }; + error = { "filter expression must at least 2 elements" }; + return {}; } optional<std::string> key = toString(arrayMember(value, 1)); if (!key) { - return Error { "filter expression key must be a string" }; + error = { "filter expression key must be a string" }; + return {}; } if (*key == "$type") { std::vector<FeatureType> values; for (std::size_t i = 2; i < arrayLength(value); ++i) { - Result<FeatureType> filterValue = toFeatureType(arrayMember(value, i)); + optional<FeatureType> filterValue = toFeatureType(arrayMember(value, i), error); if (!filterValue) { - return filterValue.error(); + return {}; } values.push_back(*filterValue); } - return TypeFilterType { std::move(values) }; + return { TypeFilterType { std::move(values) } }; } else if (*key == "$id") { std::vector<FeatureIdentifier> values; for (std::size_t i = 2; i < arrayLength(value); ++i) { - Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i)); + optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i), error); if (!filterValue) { - return filterValue.error(); + return {}; } values.push_back(*filterValue); } - return IdentifierFilterType { std::move(values) }; + return { IdentifierFilterType { std::move(values) } }; } else { std::vector<Value> values; for (std::size_t i = 2; i < arrayLength(value); ++i) { - Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, i))); + optional<Value> filterValue = normalizeValue(toValue(arrayMember(value, i)), error); if (!filterValue) { - return filterValue.error(); + return {}; } values.push_back(*filterValue); } - return FilterType { *key, std::move(values) }; + return { FilterType { *key, std::move(values) } }; } } template <class FilterType, class V> - Result<Filter> convertCompoundFilter(const V& value) const { + optional<Filter> convertCompoundFilter(const V& value, Error& error) const { std::vector<Filter> filters; for (std::size_t i = 1; i < arrayLength(value); ++i) { - Result<Filter> element = operator()(arrayMember(value, i)); + optional<Filter> element = operator()(arrayMember(value, i), error); if (!element) { - return element.error(); + return {}; } filters.push_back(*element); } - return FilterType { std::move(filters) }; + return { FilterType { std::move(filters) } }; } }; diff --git a/include/mbgl/style/conversion/function.hpp b/include/mbgl/style/conversion/function.hpp index a5979e6799..fa8af1e2be 100644 --- a/include/mbgl/style/conversion/function.hpp +++ b/include/mbgl/style/conversion/function.hpp @@ -12,18 +12,21 @@ namespace style { namespace conversion { template <class D, class R, class V> -Result<std::map<D, R>> convertStops(const V& value) { +optional<std::map<D, R>> convertStops(const V& value, Error& error) { auto stopsValue = objectMember(value, "stops"); if (!stopsValue) { - return Error { "function value must specify stops" }; + error = { "function value must specify stops" }; + return {}; } if (!isArray(*stopsValue)) { - return Error { "function stops must be an array" }; + error = { "function stops must be an array" }; + return {}; } if (arrayLength(*stopsValue) == 0) { - return Error { "function must have at least one stop" }; + error = { "function must have at least one stop" }; + return {}; } std::map<D, R> stops; @@ -31,21 +34,23 @@ Result<std::map<D, R>> convertStops(const V& value) { const auto& stopValue = arrayMember(*stopsValue, i); if (!isArray(stopValue)) { - return Error { "function stop must be an array" }; + error = { "function stop must be an array" }; + return {}; } if (arrayLength(stopValue) != 2) { - return Error { "function stop must have two elements" }; + error = { "function stop must have two elements" }; + return {}; } - Result<D> d = convert<D>(arrayMember(stopValue, 0)); + optional<D> d = convert<D>(arrayMember(stopValue, 0), error); if (!d) { - return d.error(); + return {}; } - Result<R> r = convert<R>(arrayMember(stopValue, 1)); + optional<R> r = convert<R>(arrayMember(stopValue, 1), error); if (!r) { - return r.error(); + return {}; } stops.emplace(*d, *r); @@ -59,10 +64,10 @@ struct Converter<ExponentialStops<T>> { static constexpr const char * type = "exponential"; template <class V> - Result<ExponentialStops<T>> operator()(const V& value) const { - auto stops = convertStops<float, T>(value); + optional<ExponentialStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<float, T>(value, error); if (!stops) { - return stops.error(); + return {}; } auto baseValue = objectMember(value, "base"); @@ -72,7 +77,8 @@ struct Converter<ExponentialStops<T>> { optional<float> base = toNumber(*baseValue); if (!base) { - return Error { "function base must be a number"}; + error = { "function base must be a number"}; + return {}; } return ExponentialStops<T>(*stops, *base); @@ -84,10 +90,10 @@ struct Converter<IntervalStops<T>> { static constexpr const char * type = "interval"; template <class V> - Result<IntervalStops<T>> operator()(const V& value) const { - auto stops = convertStops<float, T>(value); + optional<IntervalStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<float, T>(value, error); if (!stops) { - return stops.error(); + return {}; } return IntervalStops<T>(*stops); } @@ -96,23 +102,24 @@ struct Converter<IntervalStops<T>> { template <> struct Converter<CategoricalValue> { template <class V> - Result<CategoricalValue> operator()(const V& value) const { + optional<CategoricalValue> operator()(const V& value, Error& error) const { auto b = toBool(value); if (b) { - return *b; + return { *b }; } auto n = toNumber(value); if (n) { - return int64_t(*n); + return { int64_t(*n) }; } auto s = toString(value); if (s) { - return *s; + return { *s }; } - return Error { "stop domain value must be a number, string, or boolean" }; + error = { "stop domain value must be a number, string, or boolean" }; + return {}; } }; @@ -121,10 +128,10 @@ struct Converter<CategoricalStops<T>> { static constexpr const char * type = "categorical"; template <class V> - Result<CategoricalStops<T>> operator()(const V& value) const { - auto stops = convertStops<CategoricalValue, T>(value); + optional<CategoricalStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<CategoricalValue, T>(value, error); if (!stops) { - return stops.error(); + return {}; } return CategoricalStops<T>( std::map<CategoricalValue, T>((*stops).begin(), (*stops).end())); @@ -136,7 +143,7 @@ struct Converter<IdentityStops<T>> { static constexpr const char * type = "identity"; template <class V> - Result<IdentityStops<T>> operator()(const V&) const { + optional<IdentityStops<T>> operator()(const V&, Error&) const { return IdentityStops<T>(); } }; @@ -148,7 +155,7 @@ template <class T, class... Ts> struct StopsConverter<T, variant<Ts...>> { public: template <class V> - Result<variant<Ts...>> operator()(const V& value) const { + optional<variant<Ts...>> operator()(const V& value, Error& error) const { std::string type = util::Interpolatable<T> ? "exponential" : "interval"; auto typeValue = objectMember(value, "type"); @@ -156,16 +163,18 @@ public: type = *toString(*typeValue); } - optional<Result<variant<Ts...>>> result; + 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) { - auto stops = convert<Stops>(value); - result = stops - ? Result<variant<Ts...>>(*stops) - : Result<variant<Ts...>>(stops.error()); + matched = true; + optional<Stops> stops = convert<Stops>(value, error); + if (stops) { + result = variant<Ts...>(*stops); + } } }; @@ -173,25 +182,27 @@ public: (tryConvert((Ts*)nullptr), 0)... }); - if (!result) { - return Error { "unsupported function type" }; + if (!matched) { + error = { "unsupported function type" }; + return {}; } - return *result; + return result; } }; template <class T> struct Converter<CameraFunction<T>> { template <class V> - Result<CameraFunction<T>> operator()(const V& value) const { + optional<CameraFunction<T>> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "function must be an object" }; + error = { "function must be an object" }; + return {}; } - auto stops = StopsConverter<T, typename CameraFunction<T>::Stops>()(value); + auto stops = StopsConverter<T, typename CameraFunction<T>::Stops>()(value, error); if (!stops) { - return stops.error(); + return {}; } return CameraFunction<T>(*stops); @@ -199,46 +210,50 @@ struct Converter<CameraFunction<T>> { }; template <class T, class V> -Result<optional<T>> convertDefaultValue(const V& value) { +optional<optional<T>> convertDefaultValue(const V& value, Error& error) { auto defaultValueValue = objectMember(value, "default"); if (!defaultValueValue) { - return {}; + return optional<T>(); } - auto defaultValue = convert<T>(*defaultValueValue); + auto defaultValue = convert<T>(*defaultValueValue, error); if (!defaultValue) { - return Error { "wrong type for \"default\": " + defaultValue.error().message }; + error = { "wrong type for \"default\": " + error.message }; + return {}; } - return *defaultValue; + return { *defaultValue }; } template <class T> struct Converter<SourceFunction<T>> { template <class V> - Result<SourceFunction<T>> operator()(const V& value) const { + optional<SourceFunction<T>> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "function must be an object" }; + error = { "function must be an object" }; + return {}; } auto propertyValue = objectMember(value, "property"); if (!propertyValue) { - return Error { "function must specify property" }; + error = { "function must specify property" }; + return {}; } auto propertyString = toString(*propertyValue); if (!propertyString) { - return Error { "function property must be a string" }; + error = { "function property must be a string" }; + return {}; } - auto stops = StopsConverter<T, typename SourceFunction<T>::Stops>()(value); + auto stops = StopsConverter<T, typename SourceFunction<T>::Stops>()(value, error); if (!stops) { - return stops.error(); + return {}; } - auto defaultValue = convertDefaultValue<T>(value); + auto defaultValue = convertDefaultValue<T>(value, error); if (!defaultValue) { - return defaultValue.error(); + return {}; } return SourceFunction<T>(*propertyString, *stops, *defaultValue); @@ -253,29 +268,32 @@ struct CompositeValue : std::pair<float, S> { template <class S> struct Converter<CompositeValue<S>> { template <class V> - Result<CompositeValue<S>> operator()(const V& value) const { + optional<CompositeValue<S>> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "stop must be an object" }; + error = { "stop must be an object" }; + return {}; } auto zoomValue = objectMember(value, "zoom"); if (!zoomValue) { - return Error { "stop must specify zoom" }; + error = { "stop must specify zoom" }; + return {}; } auto propertyValue = objectMember(value, "value"); if (!propertyValue) { - return Error { "stop must specify value" }; + error = { "stop must specify value" }; + return {}; } - Result<float> z = convert<float>(*zoomValue); + optional<float> z = convert<float>(*zoomValue, error); if (!z) { - return z.error(); + return {}; } - Result<S> s = convert<S>(*propertyValue); + optional<S> s = convert<S>(*propertyValue, error); if (!s) { - return s.error(); + return {}; } return CompositeValue<S> { *z, *s }; @@ -287,10 +305,10 @@ struct Converter<CompositeExponentialStops<T>> { static constexpr const char * type = "exponential"; template <class V> - Result<CompositeExponentialStops<T>> operator()(const V& value) const { - auto stops = convertStops<CompositeValue<float>, T>(value); + optional<CompositeExponentialStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<CompositeValue<float>, T>(value, error); if (!stops) { - return stops.error(); + return {}; } auto base = 1.0f; @@ -313,10 +331,10 @@ struct Converter<CompositeIntervalStops<T>> { static constexpr const char * type = "interval"; template <class V> - Result<CompositeIntervalStops<T>> operator()(const V& value) const { - auto stops = convertStops<CompositeValue<float>, T>(value); + optional<CompositeIntervalStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<CompositeValue<float>, T>(value, error); if (!stops) { - return stops.error(); + return {}; } std::map<float, std::map<float, T>> convertedStops; @@ -333,10 +351,10 @@ struct Converter<CompositeCategoricalStops<T>> { static constexpr const char * type = "categorical"; template <class V> - Result<CompositeCategoricalStops<T>> operator()(const V& value) const { - auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value); + optional<CompositeCategoricalStops<T>> operator()(const V& value, Error& error) const { + auto stops = convertStops<CompositeValue<CategoricalValue>, T>(value, error); if (!stops) { - return stops.error(); + return {}; } std::map<float, std::map<CategoricalValue, T>> convertedStops; @@ -351,29 +369,32 @@ struct Converter<CompositeCategoricalStops<T>> { template <class T> struct Converter<CompositeFunction<T>> { template <class V> - Result<CompositeFunction<T>> operator()(const V& value) const { + optional<CompositeFunction<T>> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "function must be an object" }; + error = { "function must be an object" }; + return {}; } auto propertyValue = objectMember(value, "property"); if (!propertyValue) { - return Error { "function must specify property" }; + error = { "function must specify property" }; + return {}; } auto propertyString = toString(*propertyValue); if (!propertyString) { - return Error { "function property must be a string" }; + error = { "function property must be a string" }; + return {}; } - auto stops = StopsConverter<T, typename CompositeFunction<T>::Stops>()(value); + auto stops = StopsConverter<T, typename CompositeFunction<T>::Stops>()(value, error); if (!stops) { - return stops.error(); + return {}; } - auto defaultValue = convertDefaultValue<T>(value); + auto defaultValue = convertDefaultValue<T>(value, error); if (!defaultValue) { - return defaultValue.error(); + return {}; } return CompositeFunction<T>(*propertyString, *stops, *defaultValue); diff --git a/include/mbgl/style/conversion/geojson.hpp b/include/mbgl/style/conversion/geojson.hpp index ba10b3ecc8..6e6e97dbc0 100644 --- a/include/mbgl/style/conversion/geojson.hpp +++ b/include/mbgl/style/conversion/geojson.hpp @@ -8,7 +8,7 @@ namespace style { namespace conversion { template <class V> -Result<GeoJSON> convertGeoJSON(const V& value); +optional<GeoJSON> convertGeoJSON(const V& value, Error& error); } // namespace conversion } // namespace style diff --git a/include/mbgl/style/conversion/geojson_options.hpp b/include/mbgl/style/conversion/geojson_options.hpp index 880090b402..19383d90ce 100644 --- a/include/mbgl/style/conversion/geojson_options.hpp +++ b/include/mbgl/style/conversion/geojson_options.hpp @@ -11,7 +11,7 @@ template <> struct Converter<GeoJSONOptions> { template <class V> - Result<GeoJSONOptions> operator()(const V& value) const { + optional<GeoJSONOptions> operator()(const V& value, Error& error) const { GeoJSONOptions options; const auto maxzoomValue = objectMember(value, "maxzoom"); @@ -19,7 +19,8 @@ struct Converter<GeoJSONOptions> { if (toNumber(*maxzoomValue)) { options.maxzoom = static_cast<uint8_t>(*toNumber(*maxzoomValue)); } else { - return Error{ "GeoJSON source maxzoom value must be a number" }; + error = { "GeoJSON source maxzoom value must be a number" }; + return {}; } } @@ -28,7 +29,8 @@ struct Converter<GeoJSONOptions> { if (toNumber(*bufferValue)) { options.buffer = static_cast<uint16_t>(*toNumber(*bufferValue)); } else { - return Error{ "GeoJSON source buffer value must be a number" }; + error = { "GeoJSON source buffer value must be a number" }; + return {}; } } @@ -37,7 +39,8 @@ struct Converter<GeoJSONOptions> { if (toNumber(*toleranceValue)) { options.tolerance = static_cast<double>(*toNumber(*toleranceValue)); } else { - return Error{ "GeoJSON source tolerance value must be a number" }; + error = { "GeoJSON source tolerance value must be a number" }; + return {}; } } @@ -46,7 +49,8 @@ struct Converter<GeoJSONOptions> { if (toBool(*clusterValue)) { options.cluster = *toBool(*clusterValue); } else { - return Error{ "GeoJSON source cluster value must be a boolean" }; + error = { "GeoJSON source cluster value must be a boolean" }; + return {}; } } @@ -55,7 +59,8 @@ struct Converter<GeoJSONOptions> { if (toNumber(*clusterMaxZoomValue)) { options.clusterMaxZoom = static_cast<uint8_t>(*toNumber(*clusterMaxZoomValue)); } else { - return Error{ "GeoJSON source clusterMaxZoom value must be a number" }; + error = { "GeoJSON source clusterMaxZoom value must be a number" }; + return {}; } } @@ -64,7 +69,8 @@ struct Converter<GeoJSONOptions> { if (toNumber(*clusterRadiusValue)) { options.clusterRadius = static_cast<double>(*toNumber(*clusterRadiusValue)); } else { - return Error{ "GeoJSON source clusterRadius value must be a number" }; + error = { "GeoJSON source clusterRadius value must be a number" }; + return {}; } } diff --git a/include/mbgl/style/conversion/layer.hpp b/include/mbgl/style/conversion/layer.hpp index 0539dcf9ad..efb1df8fef 100644 --- a/include/mbgl/style/conversion/layer.hpp +++ b/include/mbgl/style/conversion/layer.hpp @@ -58,47 +58,53 @@ template <> struct Converter<std::unique_ptr<Layer>> { public: template <class V> - Result<std::unique_ptr<Layer>> operator()(const V& value) const { + optional<std::unique_ptr<Layer>> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "layer must be an object" }; + error = { "layer must be an object" }; + return {}; } auto idValue = objectMember(value, "id"); if (!idValue) { - return Error { "layer must have an id" }; + error = { "layer must have an id" }; + return {}; } optional<std::string> id = toString(*idValue); if (!id) { - return Error { "layer id must be a string" }; + error = { "layer id must be a string" }; + return {}; } auto typeValue = objectMember(value, "type"); if (!typeValue) { - return Error { "layer must have a type" }; + error = { "layer must have a type" }; + return {}; } optional<std::string> type = toString(*typeValue); if (!type) { - return Error { "layer type must be a string" }; + error = { "layer type must be a string" }; + return {}; } - Result<std::unique_ptr<Layer>> converted; + optional<std::unique_ptr<Layer>> converted; if (*type == "fill") { - converted = convertVectorLayer<FillLayer>(*id, value); + converted = convertVectorLayer<FillLayer>(*id, value, error); } else if (*type == "line") { - converted = convertVectorLayer<LineLayer>(*id, value); + converted = convertVectorLayer<LineLayer>(*id, value, error); } else if (*type == "circle") { - converted = convertVectorLayer<CircleLayer>(*id, value); + converted = convertVectorLayer<CircleLayer>(*id, value, error); } else if (*type == "symbol") { - converted = convertVectorLayer<SymbolLayer>(*id, value); + converted = convertVectorLayer<SymbolLayer>(*id, value, error); } else if (*type == "raster") { - converted = convertRasterLayer(*id, value); + converted = convertRasterLayer(*id, value, error); } else if (*type == "background") { - converted = convertBackgroundLayer(*id, value); + converted = convertBackgroundLayer(*id, value, error); } else { - return Error { "invalid layer type" }; + error = { "invalid layer type" }; + return {}; } if (!converted) { @@ -111,7 +117,8 @@ public: if (minzoomValue) { optional<float> minzoom = toNumber(*minzoomValue); if (!minzoom) { - return Error { "minzoom must be numeric" }; + error = { "minzoom must be numeric" }; + return {}; } layer->setMinZoom(*minzoom); } @@ -120,7 +127,8 @@ public: if (maxzoomValue) { optional<float> maxzoom = toNumber(*maxzoomValue); if (!maxzoom) { - return Error { "maxzoom must be numeric" }; + error = { "maxzoom must be numeric" }; + return {}; } layer->setMaxZoom(*maxzoom); } @@ -128,19 +136,22 @@ public: auto layoutValue = objectMember(value, "layout"); if (layoutValue) { if (!isObject(*layoutValue)) { - return Error { "layout must be an object" }; + error = { "layout must be an object" }; + return {}; } - optional<Error> error = eachMember(*layoutValue, [&] (const std::string& k, const V& v) { + optional<Error> error_ = eachMember(*layoutValue, [&] (const std::string& k, const V& v) { return setLayoutProperty(*layer, k, v); }); - if (error) { - return *error; + if (error_) { + error = *error_; + return {}; } } - optional<Error> error = setPaintProperties(*layer, value); - if (error) { - return *error; + optional<Error> error_ = setPaintProperties(*layer, value); + if (error_) { + error = *error_; + return {}; } return std::move(layer); @@ -148,15 +159,17 @@ public: private: template <class LayerType, class V> - Result<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value) const { + optional<std::unique_ptr<Layer>> convertVectorLayer(const std::string& id, const V& value, Error& error) const { auto sourceValue = objectMember(value, "source"); if (!sourceValue) { - return Error { "layer must have a source" }; + error = { "layer must have a source" }; + return {}; } optional<std::string> source = toString(*sourceValue); if (!source) { - return Error { "layer source must be a string" }; + error = { "layer source must be a string" }; + return {}; } std::unique_ptr<LayerType> layer = std::make_unique<LayerType>(id, *source); @@ -165,41 +178,44 @@ private: if (sourceLayerValue) { optional<std::string> sourceLayer = toString(*sourceLayerValue); if (!sourceLayer) { - return Error { "layer source-layer must be a string" }; + error = { "layer source-layer must be a string" }; + return {}; } layer->setSourceLayer(*sourceLayer); } auto filterValue = objectMember(value, "filter"); if (filterValue) { - Result<Filter> filter = convert<Filter>(*filterValue); + optional<Filter> filter = convert<Filter>(*filterValue, error); if (!filter) { - return filter.error(); + return {}; } layer->setFilter(*filter); } - return std::move(layer); + return { std::move(layer) }; } template <class V> - Result<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value) const { + optional<std::unique_ptr<Layer>> convertRasterLayer(const std::string& id, const V& value, Error& error) const { auto sourceValue = objectMember(value, "source"); if (!sourceValue) { - return Error { "layer must have a source" }; + error = { "layer must have a source" }; + return {}; } optional<std::string> source = toString(*sourceValue); if (!source) { - return Error { "layer source must be a string" }; + error = { "layer source must be a string" }; + return {}; } - return std::make_unique<RasterLayer>(id, *source); + return { std::make_unique<RasterLayer>(id, *source) }; } template <class V> - Result<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&) const { - return std::make_unique<BackgroundLayer>(id); + optional<std::unique_ptr<Layer>> convertBackgroundLayer(const std::string& id, const V&, Error&) const { + return { std::make_unique<BackgroundLayer>(id) }; } }; diff --git a/include/mbgl/style/conversion/property_setter.hpp b/include/mbgl/style/conversion/property_setter.hpp index 51ec4778d9..1f537f3c4d 100644 --- a/include/mbgl/style/conversion/property_setter.hpp +++ b/include/mbgl/style/conversion/property_setter.hpp @@ -26,9 +26,10 @@ optional<Error> setLayoutProperty(Layer& layer, const V& value) { return Error { "layer doesn't support this property" }; } - Result<PropertyValue> typedValue = convert<PropertyValue>(value); + Error error; + optional<PropertyValue> typedValue = convert<PropertyValue>(value, error); if (!typedValue) { - return typedValue.error(); + return error; } (typedLayer->*setter)(*typedValue); @@ -42,9 +43,10 @@ optional<Error> setPaintProperty(Layer& layer, const V& value, const optional<st return Error { "layer doesn't support this property" }; } - Result<PropertyValue> typedValue = convert<PropertyValue>(value); + Error error; + optional<PropertyValue> typedValue = convert<PropertyValue>(value, error); if (!typedValue) { - return typedValue.error(); + return error; } (typedLayer->*setter)(*typedValue, klass); @@ -58,9 +60,10 @@ optional<Error> setTransition(Layer& layer, const V& value, const optional<std:: return Error { "layer doesn't support this property" }; } - Result<TransitionOptions> transition = convert<TransitionOptions>(value); + Error error; + optional<TransitionOptions> transition = convert<TransitionOptions>(value, error); if (!transition) { - return transition.error(); + return error; } (typedLayer->*setter)(*transition, klass); @@ -74,9 +77,10 @@ optional<Error> setVisibility(Layer& layer, const V& value) { return {}; } - Result<VisibilityType> visibility = convert<VisibilityType>(value); + Error error; + optional<VisibilityType> visibility = convert<VisibilityType>(value, error); if (!visibility) { - return visibility.error(); + return error; } layer.setVisibility(*visibility); diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp index d5e2a5c3c8..f8937da07d 100644 --- a/include/mbgl/style/conversion/property_value.hpp +++ b/include/mbgl/style/conversion/property_value.hpp @@ -12,21 +12,21 @@ namespace conversion { template <class T> struct Converter<PropertyValue<T>> { template <class V> - Result<PropertyValue<T>> operator()(const V& value) const { + optional<PropertyValue<T>> operator()(const V& value, Error& error) const { if (isUndefined(value)) { - return {}; + return PropertyValue<T>(); } else if (isObject(value)) { - Result<CameraFunction<T>> function = convert<CameraFunction<T>>(value); + optional<CameraFunction<T>> function = convert<CameraFunction<T>>(value, error); if (!function) { - return function.error(); + return {}; } - return *function; + return { *function }; } else { - Result<T> constant = convert<T>(value); + optional<T> constant = convert<T>(value, error); if (!constant) { - return constant.error(); + return {}; } - return *constant; + return { *constant }; } } }; diff --git a/include/mbgl/style/conversion/source.hpp b/include/mbgl/style/conversion/source.hpp index 6e1b4347c3..2371183b1c 100644 --- a/include/mbgl/style/conversion/source.hpp +++ b/include/mbgl/style/conversion/source.hpp @@ -17,59 +17,65 @@ 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 { + optional<std::unique_ptr<Source>> operator()(const V& value, Error& error, const std::string& id) const { if (!isObject(value)) { - return Error{ "source must be an object" }; + error = { "source must be an object" }; + return {}; } auto typeValue = objectMember(value, "type"); if (!typeValue) { - return Error{ "source must have a type" }; + error = { "source must have a type" }; + return {}; } optional<std::string> type = toString(*typeValue); if (!type) { - return Error{ "source type must be a string" }; + error = { "source type must be a string" }; + return {}; } if (*type == "raster") { - return convertRasterSource(id, value); + return convertRasterSource(id, value, error); } else if (*type == "vector") { - return convertVectorSource(id, value); + return convertVectorSource(id, value, error); } else if (*type == "geojson") { - return convertGeoJSONSource(id, value); + return convertGeoJSONSource(id, value, error); } else { - return Error{ "invalid source type" }; + error = { "invalid source type" }; + return {}; } } 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 { + optional<variant<std::string, Tileset>> convertURLOrTileset(const V& value, Error& error) const { auto urlVal = objectMember(value, "url"); if (!urlVal) { - Result<Tileset> tileset = convert<Tileset>(value); + optional<Tileset> tileset = convert<Tileset>(value, error); if (!tileset) { - return tileset.error(); + return {}; } - return *tileset; + return { *tileset }; } optional<std::string> url = toString(*urlVal); if (!url) { - return Error{ "source url must be a string" }; + error = { "source url must be a string" }; + return {}; } - return *url; + 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); + optional<std::unique_ptr<Source>> convertRasterSource(const std::string& id, + const V& value, + Error& error) const { + optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { - return urlOrTileset.error(); + return {}; } uint16_t tileSize = util::tileSize; @@ -77,53 +83,58 @@ private: if (tileSizeValue) { optional<float> size = toNumber(*tileSizeValue); if (!size || *size < 0 || *size > std::numeric_limits<uint16_t>::max()) { - return Error{ "invalid tileSize" }; + error = { "invalid tileSize" }; + return {}; } tileSize = *size; } - return std::make_unique<RasterSource>(id, std::move(*urlOrTileset), tileSize); + 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); + optional<std::unique_ptr<Source>> convertVectorSource(const std::string& id, + const V& value, + Error& error) const { + optional<variant<std::string, Tileset>> urlOrTileset = convertURLOrTileset(value, error); if (!urlOrTileset) { - return urlOrTileset.error(); + return {}; } - return std::make_unique<VectorSource>(id, std::move(*urlOrTileset)); + 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 { + optional<std::unique_ptr<Source>> convertGeoJSONSource(const std::string& id, + const V& value, + Error& error) const { auto dataValue = objectMember(value, "data"); if (!dataValue) { - return Error{ "GeoJSON source must have a data value" }; + error = { "GeoJSON source must have a data value" }; + return {}; } - Result<GeoJSONOptions> options = convert<GeoJSONOptions>(value); + optional<GeoJSONOptions> options = convert<GeoJSONOptions>(value, error); if (!options) { - return options.error(); + return {}; } auto result = std::make_unique<GeoJSONSource>(id, *options); if (isObject(*dataValue)) { - Result<GeoJSON> geoJSON = convertGeoJSON(*dataValue); + optional<GeoJSON> geoJSON = convertGeoJSON(*dataValue, error); if (!geoJSON) { - return geoJSON.error(); + return {}; } 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" }; + error = { "GeoJSON data must be a URL or an object" }; + return {}; } - return std::move(result); + return { std::move(result) }; } }; diff --git a/include/mbgl/style/conversion/tileset.hpp b/include/mbgl/style/conversion/tileset.hpp index 1955cc16cf..377170aa6a 100644 --- a/include/mbgl/style/conversion/tileset.hpp +++ b/include/mbgl/style/conversion/tileset.hpp @@ -11,22 +11,25 @@ template <> struct Converter<Tileset> { public: template <class V> - Result<Tileset> operator()(const V& value) const { + optional<Tileset> operator()(const V& value, Error& error) const { Tileset result; auto tiles = objectMember(value, "tiles"); if (!tiles) { - return Error { "source must have tiles" }; + error = { "source must have tiles" }; + return {}; } if (!isArray(*tiles)) { - return Error { "source tiles must be an array" }; + error = { "source tiles must be an array" }; + return {}; } 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" }; + error = { "source tiles member must be a string" }; + return {}; } result.tiles.push_back(std::move(*urlTemplate)); } @@ -43,7 +46,8 @@ public: if (minzoomValue) { optional<float> minzoom = toNumber(*minzoomValue); if (!minzoom || *minzoom < 0 || *minzoom > std::numeric_limits<uint8_t>::max()) { - return Error { "invalid minzoom" }; + error = { "invalid minzoom" }; + return {}; } result.zoomRange.min = *minzoom; } @@ -52,7 +56,8 @@ public: if (maxzoomValue) { optional<float> maxzoom = toNumber(*maxzoomValue); if (!maxzoom || *maxzoom < 0 || *maxzoom > std::numeric_limits<uint8_t>::max()) { - return Error { "invalid maxzoom" }; + error = { "invalid maxzoom" }; + return {}; } result.zoomRange.max = *maxzoom; } @@ -61,7 +66,8 @@ public: if (attributionValue) { optional<std::string> attribution = toString(*attributionValue); if (!attribution) { - return Error { "source attribution must be a string" }; + error = { "source attribution must be a string" }; + return {}; } result.attribution = std::move(*attribution); } diff --git a/include/mbgl/style/conversion/transition_options.hpp b/include/mbgl/style/conversion/transition_options.hpp index cdd65cfe9f..de8834d578 100644 --- a/include/mbgl/style/conversion/transition_options.hpp +++ b/include/mbgl/style/conversion/transition_options.hpp @@ -11,9 +11,10 @@ template <> struct Converter<TransitionOptions> { public: template <class V> - Result<TransitionOptions> operator()(const V& value) const { + optional<TransitionOptions> operator()(const V& value, Error& error) const { if (!isObject(value)) { - return Error { "transition must be an object" }; + error = { "transition must be an object" }; + return {}; } TransitionOptions result; @@ -22,7 +23,8 @@ public: if (duration) { auto number = toNumber(*duration); if (!number) { - return Error { "duration must be a number" }; + error = { "duration must be a number" }; + return {}; } result.duration = { std::chrono::milliseconds(int64_t(*number)) }; } @@ -31,7 +33,8 @@ public: if (delay) { auto number = toNumber(*delay); if (!number) { - return Error { "delay must be a number" }; + error = { "delay must be a number" }; + return {}; } result.delay = { std::chrono::milliseconds(int64_t(*number)) }; } |