#include #include #include namespace mbgl { namespace style { namespace expression { EvaluationResult ArrayAssertion::evaluate(const EvaluationContext& params) const { auto result = input->evaluate(params); if (!result) { return result.error(); } type::Type expected = getType(); type::Type actual = typeOf(*result); if (checkSubtype(expected, actual)) { return EvaluationError { "Expected value to be of type " + toString(expected) + ", but found " + toString(actual) + " instead." }; } return *result; } void ArrayAssertion::eachChild(const std::function& visit) const { visit(*input); } using namespace mbgl::style::conversion; ParseResult ArrayAssertion::parse(const Convertible& value, ParsingContext& ctx) { static std::unordered_map itemTypes { {"string", type::String}, {"number", type::Number}, {"boolean", type::Boolean} }; auto length = arrayLength(value); if (length < 2 || length > 4) { ctx.error("Expected 1, 2, or 3 arguments, but found " + util::toString(length - 1) + " instead."); return ParseResult(); } optional itemType; optional N; if (length > 2) { optional itemTypeName = toString(arrayMember(value, 1)); auto it = itemTypeName ? itemTypes.find(*itemTypeName) : itemTypes.end(); if (it == itemTypes.end()) { ctx.error( R"(The item type argument of "array" must be one of string, number, boolean)", 1 ); return ParseResult(); } itemType = it->second; } else { itemType = {type::Value}; } if (length > 3) { auto n = toNumber(arrayMember(value, 2)); if (!n || *n != std::floor(*n)) { ctx.error( R"(The length argument to "array" must be a positive integer literal.)", 2 ); return ParseResult(); } N = optional(*n); } auto input = ctx.parse(arrayMember(value, length - 1), length - 1, {type::Value}); if (!input) { return input; } return ParseResult(std::make_unique( type::Array(*itemType, N), std::move(*input) )); } mbgl::Value ArrayAssertion::serialize() const { std::vector serialized; serialized.emplace_back(getOperator()); const auto array = getType().get(); if (array.itemType.is() || array.itemType.is() || array.itemType.is()) { serialized.emplace_back(type::toString(array.itemType)); if (array.N) { serialized.emplace_back(uint64_t(*array.N)); } } serialized.emplace_back(input->serialize()); return serialized; } } // namespace expression } // namespace style } // namespace mbgl