summaryrefslogtreecommitdiff
path: root/src/mbgl/style/expression/match.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl/style/expression/match.cpp')
-rw-r--r--src/mbgl/style/expression/match.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/mbgl/style/expression/match.cpp b/src/mbgl/style/expression/match.cpp
index 0b2790b688..3d41f0bdd3 100644
--- a/src/mbgl/style/expression/match.cpp
+++ b/src/mbgl/style/expression/match.cpp
@@ -40,6 +40,42 @@ std::vector<optional<Value>> Match<T>::possibleOutputs() const {
return result;
}
+template <typename T>
+mbgl::Value Match<T>::serialize() const {
+ std::vector<mbgl::Value> serialized;
+ serialized.emplace_back(getOperator());
+ serialized.emplace_back(input->serialize());
+
+ // Sort so serialization has an arbitrary defined order, even though branch order doesn't affect evaluation
+ std::map<T, std::shared_ptr<Expression>> sortedBranches(branches.begin(), branches.end());
+
+ // Group branches by unique match expression to support condensed serializations
+ // of the form [case1, case2, ...] -> matchExpression
+ std::map<Expression*, size_t> outputLookup;
+ std::vector<std::pair<Expression*, std::vector<mbgl::Value>>> groupedByOutput;
+ for (auto& entry : sortedBranches) {
+ auto outputIndex = outputLookup.find(entry.second.get());
+ if (outputIndex == outputLookup.end()) {
+ // First time seeing this output, add it to the end of the grouped list
+ outputLookup[entry.second.get()] = groupedByOutput.size();
+ groupedByOutput.emplace_back(entry.second.get(), std::vector<mbgl::Value>{{entry.first}});
+ } else {
+ // We've seen this expression before, add the label to that output's group
+ groupedByOutput[outputIndex->second].second.emplace_back(entry.first);
+ }
+ };
+
+ for (auto& entry : groupedByOutput) {
+ entry.second.size() == 1
+ ? serialized.emplace_back(entry.second[0]) // Only a single label matches this output expression
+ : serialized.emplace_back(entry.second); // Array of literal labels pointing to this output expression
+ serialized.emplace_back(entry.first->serialize()); // The output expression itself
+ }
+
+ serialized.emplace_back(otherwise->serialize());
+ return serialized;
+}
+
template<> EvaluationResult Match<std::string>::evaluate(const EvaluationContext& params) const {
const EvaluationResult inputValue = input->evaluate(params);