diff options
Diffstat (limited to 'src/mbgl/style/expression/match.cpp')
-rw-r--r-- | src/mbgl/style/expression/match.cpp | 36 |
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); |