#include #include #include #include namespace mbgl { namespace style { namespace expression { type::Type typeOf(const Value& value) { return value.match([&](bool) -> type::Type { return type::Boolean; }, [&](double) -> type::Type { return type::Number; }, [&](const std::string&) -> type::Type { return type::String; }, [&](const Color&) -> type::Type { return type::Color; }, [&](const Collator&) -> type::Type { return type::Collator; }, [&](const Formatted&) -> type::Type { return type::Formatted; }, [&](const Image&) -> type::Type { return type::Image; }, [&](const NullValue&) -> type::Type { return type::Null; }, [&](const std::unordered_map&) -> type::Type { return type::Object; }, [&](const std::vector& arr) -> type::Type { optional itemType; for (const auto& item : arr) { const type::Type t = typeOf(item); if (!itemType) { itemType = {t}; } else if (*itemType == t) { continue; } else { itemType = {type::Value}; break; } } return type::Array(itemType.value_or(type::Value), arr.size()); }); } std::string toString(const Value& value) { return value.match([](const NullValue&) { return std::string(); }, [](const Color& c) { return c.stringify(); }, // avoid quoting [](const Formatted& f) { return f.toString(); }, [](const Image& i) { return i.id(); }, [](const std::string& s) { return s; }, // avoid quoting [](const auto& v_) { return stringify(v_); }); } void writeJSON(rapidjson::Writer& writer, const Value& value) { value.match([&](const NullValue&) { writer.Null(); }, [&](bool b) { writer.Bool(b); }, [&](double f) { // make sure integer values are stringified without trailing ".0". f == std::floor(f) ? writer.Int(f) : writer.Double(f); }, [&](const std::string& s) { writer.String(s); }, [&](const Color& c) { writer.String(c.stringify()); }, [&](const Collator&) { // Collators are excluded from constant folding and there's no Literal parser // for them so there shouldn't be any way to serialize this value. assert(false); }, [&](const Formatted& f) { // `stringify` in turns calls ValueConverter::fromExpressionValue below // Serialization strategy for Formatted objects is to return the constant // expression that would generate them. mbgl::style::conversion::stringify(writer, f); }, [&](const Image& i) { mbgl::style::conversion::stringify(writer, i); }, [&](const std::vector& arr) { writer.StartArray(); for (const auto& item : arr) { writeJSON(writer, item); } writer.EndArray(); }, [&](const std::unordered_map& obj) { writer.StartObject(); for (const auto& entry : obj) { writer.Key(entry.first.c_str()); writeJSON(writer, entry.second); } writer.EndObject(); }); } std::string stringify(const Value& value) { rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); writeJSON(writer, value); return buffer.GetString(); } struct FromMBGLValue { Value operator()(const std::vector& v) { std::vector result; result.reserve(v.size()); for(const auto& item : v) { result.emplace_back(toExpressionValue(item)); } return result; } Value operator()(const std::unordered_map& v) { std::unordered_map result; result.reserve(v.size()); for(const auto& entry : v) { result.emplace(entry.first, toExpressionValue(entry.second)); } return result; } Value operator()(const std::string& s) { return s; } Value operator()(const bool b) { return b; } Value operator()(const NullValue) { return Null; } Value operator()(const double v) { return v; } Value operator()(const uint64_t& v) { return static_cast(v); } Value operator()(const int64_t& v) { return static_cast(v); } }; Value ValueConverter::toExpressionValue(const mbgl::Value& value) { return mbgl::Value::visit(value, FromMBGLValue()); } mbgl::Value ValueConverter::fromExpressionValue(const Value& value) { return value.match( [&](const Color& color) -> mbgl::Value { return color.serialize(); }, [&](const Collator&) -> mbgl::Value { // fromExpressionValue can't be used for Collator values, // because they have no meaningful representation as an mbgl::Value assert(false); return mbgl::Value(); }, [&](const Formatted& formatted) -> mbgl::Value { // Serialization strategy for Formatted objects is to return the constant // expression that would generate them. std::vector serialized; static std::string formatOperator("format"); serialized.emplace_back(formatOperator); for (const auto& section : formatted.sections) { if (section.image) { serialized.emplace_back(std::vector{std::string("image"), section.image->id()}); continue; } serialized.emplace_back(section.text); std::unordered_map options; if (section.fontScale) { options.emplace("font-scale", *section.fontScale); } if (section.fontStack) { std::vector fontStack; for (const auto& font : *section.fontStack) { fontStack.emplace_back(font); } options.emplace("text-font", std::vector{ std::string("literal"), fontStack }); } if (section.textColor) { options.emplace("text-color", fromExpressionValue(*section.textColor)); } serialized.emplace_back(options); } return serialized; }, [&](const Image& i) -> mbgl::Value { return i.toValue(); }, [&](const std::vector& values) -> mbgl::Value { std::vector converted; converted.reserve(values.size()); for (const Value& v : values) { converted.emplace_back(fromExpressionValue(v)); } return converted; }, [&](const std::unordered_map& values) -> mbgl::Value { std::unordered_map converted; converted.reserve(values.size()); for(const auto& entry : values) { converted.emplace(entry.first, fromExpressionValue(entry.second)); } return converted; }, [&](const auto& a) -> mbgl::Value { return a; }); } Value ValueConverter::toExpressionValue(const float value) { return static_cast(value); } optional ValueConverter::fromExpressionValue(const Value& value) { return value.template is() ? static_cast(value.template get()) : optional(); } template std::vector toArrayValue(const Container& value) { std::vector result; result.reserve(value.size()); for (const T& item : value) { result.push_back(ValueConverter::toExpressionValue(item)); } return result; } template Value ValueConverter>::toExpressionValue(const std::array& value) { return toArrayValue(value); } template optional> ValueConverter>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::vector& v) -> optional> { if (v.size() != N) return optional>(); std::array result; auto it = result.begin(); for(const Value& item : v) { optional convertedItem = ValueConverter::fromExpressionValue(item); if (!convertedItem) { return optional>(); } *it = *convertedItem; it = std::next(it); } return result; }, [&] (const auto&) { return optional>(); } ); } template Value ValueConverter>::toExpressionValue(const std::vector& value) { return toArrayValue(value); } template optional> ValueConverter>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::vector& v) -> optional> { std::vector result; result.reserve(v.size()); for(const Value& item : v) { optional convertedItem = ValueConverter::fromExpressionValue(item); if (!convertedItem) { return optional>(); } result.push_back(*convertedItem); } return result; }, [&] (const auto&) { return optional>(); } ); } Value ValueConverter::toExpressionValue(const mbgl::style::Position& value) { return ValueConverter>::toExpressionValue(value.getSpherical()); } optional ValueConverter::fromExpressionValue(const Value& v) { auto pos = ValueConverter>::fromExpressionValue(v); return pos ? optional(Position(*pos)) : optional(); } Value ValueConverter::toExpressionValue(const mbgl::style::Rotation& value) { return ValueConverter::toExpressionValue(value.getAngle()); } optional ValueConverter::fromExpressionValue(const Value& v) { auto angle = ValueConverter::fromExpressionValue(v); return angle ? optional(Rotation(*angle)) : optional(); } template Value ValueConverter::value >>::toExpressionValue(const T& value) { return std::string(Enum::toString(value)); } template optional ValueConverter::value >>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::string& v) { return Enum::toEnum(v); }, [&] (const auto&) { return optional(); } ); } template type::Type valueTypeToExpressionType() { return ValueConverter::expressionType(); } template <> type::Type valueTypeToExpressionType() { return type::Value; } template <> type::Type valueTypeToExpressionType() { return type::Null; } template <> type::Type valueTypeToExpressionType() { return type::Boolean; } template <> type::Type valueTypeToExpressionType() { return type::Number; } template <> type::Type valueTypeToExpressionType() { return type::String; } template <> type::Type valueTypeToExpressionType() { return type::Color; } template <> type::Type valueTypeToExpressionType() { return type::Collator; } template <> type::Type valueTypeToExpressionType() { return type::Formatted; } template <> type::Type valueTypeToExpressionType() { return type::Image; } template <> type::Type valueTypeToExpressionType>() { return type::Object; } template <> type::Type valueTypeToExpressionType>() { return type::Array(type::Value); } // used only for the special (and private) "error" expression template <> type::Type valueTypeToExpressionType() { return type::Error; } // for to_rgba expression template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; // for LocationIndicator position template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; // layout/paint property types template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; } // namespace expression } // namespace style } // namespace mbgl