summaryrefslogtreecommitdiff
path: root/include/mbgl/style
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-03-07 17:00:53 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-03-23 13:31:13 -0700
commitd7227e13a7a87cf50a4c8c1f0615fc565f5a2679 (patch)
treeeda76a2da3220f3cfeec901400369cf9c8361f58 /include/mbgl/style
parent1c757cce34344dfecc9a724034680225143f92b7 (diff)
downloadqtlocation-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.hpp39
-rw-r--r--include/mbgl/style/conversion/constant.hpp63
-rw-r--r--include/mbgl/style/conversion/data_driven_property_value.hpp18
-rw-r--r--include/mbgl/style/conversion/filter.hpp157
-rw-r--r--include/mbgl/style/conversion/function.hpp175
-rw-r--r--include/mbgl/style/conversion/geojson.hpp2
-rw-r--r--include/mbgl/style/conversion/geojson_options.hpp20
-rw-r--r--include/mbgl/style/conversion/layer.hpp88
-rw-r--r--include/mbgl/style/conversion/property_setter.hpp20
-rw-r--r--include/mbgl/style/conversion/property_value.hpp16
-rw-r--r--include/mbgl/style/conversion/source.hpp79
-rw-r--r--include/mbgl/style/conversion/tileset.hpp20
-rw-r--r--include/mbgl/style/conversion/transition_options.hpp11
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)) };
}