1 #pragma once
2 
3 #include <mbgl/style/expression/collator.hpp>
4 #include <mbgl/style/expression/type.hpp>
5 #include <mbgl/style/position.hpp>
6 #include <mbgl/style/types.hpp>
7 #include <mbgl/util/color.hpp>
8 #include <mbgl/util/enum.hpp>
9 #include <mbgl/util/feature.hpp>
10 #include <mbgl/util/variant.hpp>
11 
12 #include <array>
13 #include <vector>
14 
15 namespace mbgl {
16 namespace style {
17 namespace expression {
18 
19 struct Value;
20 
21 using ValueBase = variant<
22     NullValue,
23     bool,
24     double,
25     std::string,
26     Color,
27     Collator,
28     mapbox::util::recursive_wrapper<std::vector<Value>>,
29     mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>;
30 struct Value : ValueBase {
31     using ValueBase::ValueBase;
32 
33     // Javascript's Number.MAX_SAFE_INTEGER
maxSafeIntegermbgl::style::expression::Value34     static uint64_t maxSafeInteger() { return 9007199254740991ULL; }
35 
isSafeIntegermbgl::style::expression::Value36     static bool isSafeInteger(uint64_t x) { return x <= maxSafeInteger(); };
isSafeIntegermbgl::style::expression::Value37     static bool isSafeInteger(int64_t x) {
38         return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger();
39     }
isSafeIntegermbgl::style::expression::Value40     static bool isSafeInteger(double x) {
41         return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger();
42     }
43 
44 };
45 
46 constexpr NullValue Null = NullValue();
47 
48 type::Type typeOf(const Value& value);
49 std::string stringify(const Value& value);
50 
51 /*
52   Returns a Type object representing the expression type that corresponds to
53   the value type T.  (Specialized for primitives and specific array types in
54   the .cpp.)
55 */
56 template <typename T>
57 type::Type valueTypeToExpressionType();
58 
59 /*
60   Conversions between style value types and expression::Value
61 */
62 
63 template <class T, class Enable = void>
64 struct ValueConverter {
toExpressionValuembgl::style::expression::ValueConverter65     static Value toExpressionValue(const T& value) {
66         return Value(value);
67     }
68 
fromExpressionValuembgl::style::expression::ValueConverter69     static optional<T> fromExpressionValue(const Value& value) {
70         return value.template is<T>() ? value.template get<T>() : optional<T>();
71     }
72 };
73 
74 template <>
75 struct ValueConverter<Value> {
expressionTypembgl::style::expression::ValueConverter76     static type::Type expressionType() { return type::Value; }
toExpressionValuembgl::style::expression::ValueConverter77     static Value toExpressionValue(const Value& value) { return value; }
fromExpressionValuembgl::style::expression::ValueConverter78     static optional<Value> fromExpressionValue(const Value& value) { return value; }
79 };
80 
81 template <>
82 struct ValueConverter<mbgl::Value> {
83     static Value toExpressionValue(const mbgl::Value& value);
84     static mbgl::Value fromExpressionValue(const Value& value);
85 };
86 
87 template <>
88 struct ValueConverter<float> {
expressionTypembgl::style::expression::ValueConverter89     static type::Type expressionType() { return type::Number; }
90     static Value toExpressionValue(const float value);
91     static optional<float> fromExpressionValue(const Value& value);
92 };
93 
94 template <typename T, std::size_t N>
95 struct ValueConverter<std::array<T, N>> {
expressionTypembgl::style::expression::ValueConverter96     static type::Type expressionType() {
97         return type::Array(valueTypeToExpressionType<T>(), N);
98     }
99     static Value toExpressionValue(const std::array<T, N>& value);
100     static optional<std::array<T, N>> fromExpressionValue(const Value& value);
101 };
102 
103 template <typename T>
104 struct ValueConverter<std::vector<T>> {
expressionTypembgl::style::expression::ValueConverter105     static type::Type expressionType() {
106         return type::Array(valueTypeToExpressionType<T>());
107     }
108     static Value toExpressionValue(const std::vector<T>& value);
109     static optional<std::vector<T>> fromExpressionValue(const Value& value);
110 };
111 
112 template <>
113 struct ValueConverter<Position> {
expressionTypembgl::style::expression::ValueConverter114     static type::Type expressionType() { return type::Array(type::Number, 3); }
115     static Value toExpressionValue(const mbgl::style::Position& value);
116     static optional<Position> fromExpressionValue(const Value& v);
117 };
118 
119 template <typename T>
120 struct ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >> {
expressionTypembgl::style::expression::ValueConverter121     static type::Type expressionType() { return type::String; }
122     static Value toExpressionValue(const T& value);
123     static optional<T> fromExpressionValue(const Value& value);
124 };
125 
126 template <typename T>
toExpressionValue(const T & value)127 Value toExpressionValue(const T& value) {
128     return ValueConverter<T>::toExpressionValue(value);
129 }
130 
131 template <typename T>
fromExpressionValue(const Value & value)132 optional<T> fromExpressionValue(const Value& value) {
133     return ValueConverter<T>::fromExpressionValue(value);
134 }
135 
136 template <typename T>
fromExpressionValues(const std::vector<optional<Value>> & values)137 std::vector<optional<T>> fromExpressionValues(const std::vector<optional<Value>>& values) {
138     std::vector<optional<T>> result;
139     for (const auto& value : values) {
140         result.push_back(value ? fromExpressionValue<T>(*value) : nullopt);
141     }
142     return result;
143 }
144 
145 } // namespace expression
146 } // namespace style
147 } // namespace mbgl
148