Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[all] Replace Result<T> with optional<T> plus out Error parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
jfirebaugh committed Mar 23, 2017
1 parent 1c757cc commit d7227e1
Show file tree
Hide file tree
Showing 36 changed files with 550 additions and 486 deletions.
3 changes: 2 additions & 1 deletion benchmark/parse/filter.benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ using namespace mbgl;
style::Filter parse(const char* expression) {
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> doc;
doc.Parse<0>(expression);
return *style::conversion::convert<style::Filter, JSValue>(doc);
style::conversion::Error error;
return *style::conversion::convert<style::Filter, JSValue>(doc, error);
}

static void Parse_Filter(benchmark::State& state) {
Expand Down
2 changes: 0 additions & 2 deletions cmake/core-files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,6 @@ set(MBGL_CORE_FILES
src/mbgl/style/possibly_evaluated_property_value.hpp
src/mbgl/style/property_evaluation_parameters.hpp
src/mbgl/style/property_evaluator.hpp
src/mbgl/style/property_parsing.cpp
src/mbgl/style/property_parsing.hpp
src/mbgl/style/rapidjson_conversion.hpp
src/mbgl/style/source.cpp
src/mbgl/style/source_impl.cpp
Expand Down
39 changes: 7 additions & 32 deletions include/mbgl/style/conversion.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <mbgl/util/variant.hpp>
#include <mbgl/util/optional.hpp>

#include <string>

Expand All @@ -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&`:
Expand Down Expand Up @@ -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
Expand Down
63 changes: 39 additions & 24 deletions include/mbgl/style/conversion/constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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 }};
Expand All @@ -106,17 +115,19 @@ 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));
optional<float> second = toNumber(arrayMember(value, 1));
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 }};
Expand All @@ -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;
Expand All @@ -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);
}
Expand All @@ -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;
Expand All @@ -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);
}
Expand Down
18 changes: 9 additions & 9 deletions include/mbgl/style/conversion/data_driven_property_value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit d7227e1

Please sign in to comment.