diff --git a/include/mbgl/platform/event.hpp b/include/mbgl/platform/event.hpp index 0b3b79df6be..ee1ce6fa4e5 100644 --- a/include/mbgl/platform/event.hpp +++ b/include/mbgl/platform/event.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include namespace mbgl { @@ -13,14 +11,6 @@ enum class EventSeverity : uint8_t { Error, }; -MBGL_DEFINE_ENUM_CLASS(EventSeverityClass, EventSeverity, { - { EventSeverity::Debug, "DEBUG" }, - { EventSeverity::Info, "INFO" }, - { EventSeverity::Warning, "WARNING" }, - { EventSeverity::Error, "ERROR" }, - { EventSeverity(-1), "UNKNOWN" }, -}); - enum class Event : uint8_t { General, Setup, @@ -40,27 +30,6 @@ enum class Event : uint8_t { Glyph, }; -MBGL_DEFINE_ENUM_CLASS(EventClass, Event, { - { Event::General, "General" }, - { Event::Setup, "Setup" }, - { Event::Shader, "Shader" }, - { Event::ParseStyle, "ParseStyle" }, - { Event::ParseTile, "ParseTile" }, - { Event::Render, "Render" }, - { Event::Style, "Style" }, - { Event::Database, "Database" }, - { Event::HttpRequest, "HttpRequest" }, - { Event::Sprite, "Sprite" }, - { Event::Image, "Image" }, - { Event::OpenGL, "OpenGL" }, - { Event::JNI, "JNI" }, - { Event::Android, "Android" }, - { Event::Crash, "Crash" }, - { Event::Glyph, "Glyph" }, - { Event(-1), "Unknown" }, -}); - - struct EventPermutation { const EventSeverity severity; const Event event; diff --git a/include/mbgl/style/types.hpp b/include/mbgl/style/types.hpp index 27b524a800f..5276c9bb1fa 100644 --- a/include/mbgl/style/types.hpp +++ b/include/mbgl/style/types.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace mbgl { @@ -13,14 +13,6 @@ enum class SourceType : uint8_t { Annotations }; -MBGL_DEFINE_ENUM_CLASS(SourceTypeClass, SourceType, { - { SourceType::Vector, "vector" }, - { SourceType::Raster, "raster" }, - { SourceType::GeoJSON, "geojson" }, - { SourceType::Video, "video" }, - { SourceType::Annotations, "annotations" }, -}); - namespace style { enum class VisibilityType : bool { diff --git a/include/mbgl/util/enum.hpp b/include/mbgl/util/enum.hpp index 3fbf313aedf..9783c192bc0 100644 --- a/include/mbgl/util/enum.hpp +++ b/include/mbgl/util/enum.hpp @@ -1,52 +1,36 @@ #pragma once -#include +#include + +#include +#include #include namespace mbgl { -template -struct EnumValue { - const Type value; - const char *name; -}; - -template *names, const size_t length> -struct Enum { - using Type = EnumName; - Type value; - static const constexpr size_t l = length; -private: - static constexpr inline bool compare(const char *a, const char *b) { - return *a == *b && (*a == '\0' || compare(a + 1, b + 1)); - } - static constexpr inline const char *lookup_type(Type e, EnumValue const * const list, size_t r) { - return r == 0 ? "" : list->value == e ? list->name : lookup_type(e, list + 1, r - 1); - } - static constexpr inline Type lookup_name(const char *n, EnumValue const * const list, size_t r) { - return r == 0 ? Type(-1) : compare(list->name, n) ? list->value : lookup_name(n, list + 1, r - 1); - } +template +class Enum { public: - inline constexpr Enum(const char *n) : value(lookup_name(n, names, length)) {} - inline constexpr Enum(const std::string &n) : value(lookup_name(n.c_str(), names, length)) {} - inline constexpr Enum(Type t) : value(t) {} - - inline void operator=(const char *n) { value = lookup_name(n, names, length); } - inline void operator=(const std::string &n) { *this = n.c_str(); } - inline void operator=(Type t) { value = t; } + using Value = std::pair; - inline constexpr bool valid() const { return value != Type(-1); } + static const char * toString(T t) { + auto it = std::find_if(begin, end, [&] (const auto& v) { return t == v.first; }); + assert(it != end); return it->second; + } - inline constexpr const char *c_str() const { return lookup_type(value, names, length); } - inline std::string str() const { return c_str(); } + static optional toEnum(const std::string& s) { + auto it = std::find_if(begin, end, [&] (const auto& v) { return s == v.second; }); + return it == end ? optional() : it->first; + } - inline constexpr operator Type() const { return value; } +private: + static const Value* begin; + static const Value* end; }; -#define MBGL_DEFINE_ENUM_CLASS(name, type, strings...) \ - const constexpr ::mbgl::EnumValue type##_names[] = strings; \ - using name = ::mbgl::Enum)>; \ - inline std::ostream& operator<<(std::ostream& os, type t) { return os << name(t).str(); } +#define MBGL_DEFINE_ENUM(type, strings...) \ +const constexpr Enum::Value type##_names[] = strings; \ +template <> const Enum::Value* Enum::begin = std::begin(type##_names); \ +template <> const Enum::Value* Enum::end = std::end(type##_names); } // namespace mbgl - diff --git a/platform/darwin/src/log_nslog.mm b/platform/darwin/src/log_nslog.mm index a2e31968ab1..49583ae3c45 100644 --- a/platform/darwin/src/log_nslog.mm +++ b/platform/darwin/src/log_nslog.mm @@ -1,4 +1,5 @@ #include +#include #import @@ -7,7 +8,7 @@ void Log::platformRecord(EventSeverity severity, const std::string &msg) { NSString *message = [[NSString alloc] initWithBytes:msg.data() length:msg.size() encoding:NSUTF8StringEncoding]; - NSLog(@"[%s] %@", EventSeverityClass(severity).c_str(), message); + NSLog(@"[%s] %@", Enum::toString(severity), message); } } diff --git a/platform/default/log_stderr.cpp b/platform/default/log_stderr.cpp index 536841617a7..145cdeda03d 100644 --- a/platform/default/log_stderr.cpp +++ b/platform/default/log_stderr.cpp @@ -1,11 +1,12 @@ #include +#include #include namespace mbgl { void Log::platformRecord(EventSeverity severity, const std::string &msg) { - std::cerr << "[" << severity << "] " << msg << std::endl; + std::cerr << "[" << Enum::toString(severity) << "] " << msg << std::endl; } } // namespace mbgl diff --git a/platform/node/src/node_log.cpp b/platform/node/src/node_log.cpp index a741109b27e..21eaa55bcad 100644 --- a/platform/node/src/node_log.cpp +++ b/platform/node/src/node_log.cpp @@ -1,6 +1,8 @@ #include "node_log.hpp" #include "util/async_queue.hpp" +#include + namespace node_mbgl { struct NodeLogObserver::LogMessage { @@ -23,10 +25,10 @@ NodeLogObserver::NodeLogObserver(v8::Local target) auto msg = Nan::New(); Nan::Set(msg, Nan::New("class").ToLocalChecked(), - Nan::New(mbgl::EventClass(message.event).c_str()).ToLocalChecked()); + Nan::New(mbgl::Enum::toString(message.event)).ToLocalChecked()); Nan::Set(msg, Nan::New("severity").ToLocalChecked(), - Nan::New(mbgl::EventSeverityClass(message.severity).c_str()).ToLocalChecked()); + Nan::New(mbgl::Enum::toString(message.severity)).ToLocalChecked()); if (message.code != -1) { Nan::Set(msg, Nan::New("code").ToLocalChecked(), diff --git a/src/mbgl/platform/event.cpp b/src/mbgl/platform/event.cpp new file mode 100644 index 00000000000..68d75a29417 --- /dev/null +++ b/src/mbgl/platform/event.cpp @@ -0,0 +1,34 @@ +#include +#include + +namespace mbgl { + +MBGL_DEFINE_ENUM(EventSeverity, { + { EventSeverity::Debug, "DEBUG" }, + { EventSeverity::Info, "INFO" }, + { EventSeverity::Warning, "WARNING" }, + { EventSeverity::Error, "ERROR" }, + { EventSeverity(-1), "UNKNOWN" }, +}); + +MBGL_DEFINE_ENUM(Event, { + { Event::General, "General" }, + { Event::Setup, "Setup" }, + { Event::Shader, "Shader" }, + { Event::ParseStyle, "ParseStyle" }, + { Event::ParseTile, "ParseTile" }, + { Event::Render, "Render" }, + { Event::Style, "Style" }, + { Event::Database, "Database" }, + { Event::HttpRequest, "HttpRequest" }, + { Event::Sprite, "Sprite" }, + { Event::Image, "Image" }, + { Event::OpenGL, "OpenGL" }, + { Event::JNI, "JNI" }, + { Event::Android, "Android" }, + { Event::Crash, "Crash" }, + { Event::Glyph, "Glyph" }, + { Event(-1), "Unknown" }, +}); + +} // namespace mbgl diff --git a/src/mbgl/platform/log.cpp b/src/mbgl/platform/log.cpp index 2118511592a..4b56435df0c 100644 --- a/src/mbgl/platform/log.cpp +++ b/src/mbgl/platform/log.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -54,7 +55,7 @@ void Log::record(EventSeverity severity, Event event, int64_t code, const std::s logStream << "{" << name << "}"; #endif - logStream << "[" << event << "]"; + logStream << "[" << Enum::toString(event) << "]"; if (code >= 0) { logStream << "(" << code << ")"; diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp index 28a7d2e81bb..e625b3e5d53 100644 --- a/src/mbgl/style/parser.cpp +++ b/src/mbgl/style/parser.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -161,11 +162,15 @@ void Parser::parseSources(const JSValue& value) { const JSValue& typeVal = sourceVal["type"]; if (!typeVal.IsString()) { - Log::Warning(Event::ParseStyle, "source type must have one of the enum values"); + Log::Warning(Event::ParseStyle, "source type must be a string"); continue; } - const auto type = SourceTypeClass({ typeVal.GetString(), typeVal.GetStringLength() }); + const auto type = Enum::toEnum({ typeVal.GetString(), typeVal.GetStringLength() }); + if (!type) { + Log::Warning(Event::ParseStyle, "source type must have one of the enum values"); + continue; + } // Sources can have URLs, either because they reference an external TileJSON file, or // because reference a GeoJSON file. They don't have to have one though when all source @@ -177,7 +182,7 @@ void Parser::parseSources(const JSValue& value) { std::unique_ptr tileset; std::unique_ptr geojsonvt; - switch (type) { + switch (*type) { case SourceType::Raster: if (sourceVal.HasMember("tileSize")) { const JSValue& tileSizeVal = sourceVal["tileSize"]; @@ -236,7 +241,7 @@ void Parser::parseSources(const JSValue& value) { } const std::string id { nameVal.GetString(), nameVal.GetStringLength() }; - std::unique_ptr source = std::make_unique(type, id, url, tileSize, std::move(tileset), std::move(geojsonvt)); + std::unique_ptr source = std::make_unique(*type, id, url, tileSize, std::move(tileset), std::move(geojsonvt)); sourcesMap.emplace(id, source.get()); sources.emplace_back(std::move(source)); @@ -481,21 +486,25 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique } } -MBGL_DEFINE_ENUM_CLASS(VisibilityTypeClass, VisibilityType, { - { VisibilityType::Visible, "visible" }, - { VisibilityType::None, "none" }, -}); - void Parser::parseVisibility(Layer& layer, const JSValue& value) { Layer::Impl& impl = *layer.baseImpl; + if (!value.HasMember("visibility")) { return; - } else if (!value["visibility"].IsString()) { + } + + if (!value["visibility"].IsString()) { Log::Warning(Event::ParseStyle, "value of 'visibility' must be a string"); - impl.visibility = VisibilityType::Visible; return; } - impl.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); + + const auto enumValue = Enum::toEnum({ value["visibility"].GetString(), value["visibility"].GetStringLength() }); + if (!enumValue) { + Log::Warning(Event::ParseStyle, "value of 'visibility' must be a valid enumeration value"); + return; + } + + impl.visibility = *enumValue; } Value parseFeatureType(const Value& value) { diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp index 9f60ddf3b63..9985cc7f39c 100644 --- a/src/mbgl/style/property_parsing.cpp +++ b/src/mbgl/style/property_parsing.cpp @@ -55,154 +55,6 @@ optional parseConstant(const char* name, const JSValue& value) { css_color.a}}; } -MBGL_DEFINE_ENUM_CLASS(TranslateAnchorTypeClass, TranslateAnchorType, { - { TranslateAnchorType::Map, "map" }, - { TranslateAnchorType::Viewport, "viewport" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { TranslateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(RotateAnchorTypeClass, RotateAnchorType, { - { RotateAnchorType::Map, "map" }, - { RotateAnchorType::Viewport, "viewport" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { RotateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(LineCapTypeClass, LineCapType, { - { LineCapType::Round, "round" }, - { LineCapType::Butt, "butt" }, - { LineCapType::Square, "square" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { LineCapTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(LineJoinTypeClass, LineJoinType, { - { LineJoinType::Miter, "miter" }, - { LineJoinType::Bevel, "bevel" }, - { LineJoinType::Round, "round" }, - { LineJoinType::FakeRound, "fakeround" }, - { LineJoinType::FlipBevel, "flipbevel" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { LineJoinTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(SymbolPlacementTypeClass, SymbolPlacementType, { - { SymbolPlacementType::Point, "point" }, - { SymbolPlacementType::Line, "line" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { SymbolPlacementTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(TextAnchorTypeClass, TextAnchorType, { - { TextAnchorType::Center, "center" }, - { TextAnchorType::Left, "left" }, - { TextAnchorType::Right, "right" }, - { TextAnchorType::Top, "top" }, - { TextAnchorType::Bottom, "bottom" }, - { TextAnchorType::TopLeft, "top-left" }, - { TextAnchorType::TopRight, "top-right" }, - { TextAnchorType::BottomLeft, "bottom-left" }, - { TextAnchorType::BottomRight, "bottom-right" } -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { TextAnchorTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(TextJustifyTypeClass, TextJustifyType, { - { TextJustifyType::Center, "center" }, - { TextJustifyType::Left, "left" }, - { TextJustifyType::Right, "right" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { TextJustifyTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(TextTransformTypeClass, TextTransformType, { - { TextTransformType::None, "none" }, - { TextTransformType::Uppercase, "uppercase" }, - { TextTransformType::Lowercase, "lowercase" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { TextTransformTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - -MBGL_DEFINE_ENUM_CLASS(RotationAlignmentTypeClass, RotationAlignmentType, { - { RotationAlignmentType::Map, "map" }, - { RotationAlignmentType::Viewport, "viewport" }, -}); - -template <> -optional parseConstant(const char* name, const JSValue& value) { - if (!value.IsString()) { - Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); - return {}; - } - - return { RotationAlignmentTypeClass({ value.GetString(), value.GetStringLength() }) }; -} - template <> optional> parseConstant(const char* name, const JSValue& value) { if (value.IsArray() && value.Size() == 2 && diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp index bb894c24078..d27a9e50313 100644 --- a/src/mbgl/style/property_parsing.hpp +++ b/src/mbgl/style/property_parsing.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -17,26 +18,33 @@ namespace mbgl { namespace style { -template +template ::value>> optional parseConstant(const char* name, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); -template <> optional parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); template <> optional> parseConstant(const char*, const JSValue&); +template +optional parseConstant(const char* name, const JSValue& value, + typename std::enable_if_t::value, void*> = nullptr) { + if (!value.IsString()) { + Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name); + return {}; + } + + const auto result = Enum::toEnum({ value.GetString(), value.GetStringLength() }); + if (!result) { + Log::Warning(Event::ParseStyle, "value of '%s' must be a valid enumeration value", name); + } + + return result; +} + template PropertyValue parseProperty(const char* name, const JSValue& value) { if (!value.IsObject()) { diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp index d7752ed3711..63687104eac 100644 --- a/src/mbgl/style/source.cpp +++ b/src/mbgl/style/source.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -197,8 +198,7 @@ std::unique_ptr Source::createTile(const OverscaledTileID& overscaledT } else if (type == SourceType::GeoJSON) { return std::make_unique(overscaledTileID, id, parameters, geojsonvt.get()); } else { - Log::Warning(Event::Style, "Source type '%s' is not implemented", - SourceTypeClass(type).c_str()); + Log::Warning(Event::Style, "Source type '%s' is not implemented", Enum::toString(type)); return nullptr; } } diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp new file mode 100644 index 00000000000..3ab8789ec23 --- /dev/null +++ b/src/mbgl/style/types.cpp @@ -0,0 +1,79 @@ +#include +#include + +namespace mbgl { + +using namespace style; + +MBGL_DEFINE_ENUM(SourceType, { + { SourceType::Vector, "vector" }, + { SourceType::Raster, "raster" }, + { SourceType::GeoJSON, "geojson" }, + { SourceType::Video, "video" }, + { SourceType::Annotations, "annotations" }, +}); + +MBGL_DEFINE_ENUM(VisibilityType, { + { VisibilityType::Visible, "visible" }, + { VisibilityType::None, "none" }, +}); + +MBGL_DEFINE_ENUM(TranslateAnchorType, { + { TranslateAnchorType::Map, "map" }, + { TranslateAnchorType::Viewport, "viewport" }, +}); + +MBGL_DEFINE_ENUM(RotateAnchorType, { + { RotateAnchorType::Map, "map" }, + { RotateAnchorType::Viewport, "viewport" }, +}); + +MBGL_DEFINE_ENUM(LineCapType, { + { LineCapType::Round, "round" }, + { LineCapType::Butt, "butt" }, + { LineCapType::Square, "square" }, +}); + +MBGL_DEFINE_ENUM(LineJoinType, { + { LineJoinType::Miter, "miter" }, + { LineJoinType::Bevel, "bevel" }, + { LineJoinType::Round, "round" }, + { LineJoinType::FakeRound, "fakeround" }, + { LineJoinType::FlipBevel, "flipbevel" }, +}); + +MBGL_DEFINE_ENUM(SymbolPlacementType, { + { SymbolPlacementType::Point, "point" }, + { SymbolPlacementType::Line, "line" }, +}); + +MBGL_DEFINE_ENUM(TextAnchorType, { + { TextAnchorType::Center, "center" }, + { TextAnchorType::Left, "left" }, + { TextAnchorType::Right, "right" }, + { TextAnchorType::Top, "top" }, + { TextAnchorType::Bottom, "bottom" }, + { TextAnchorType::TopLeft, "top-left" }, + { TextAnchorType::TopRight, "top-right" }, + { TextAnchorType::BottomLeft, "bottom-left" }, + { TextAnchorType::BottomRight, "bottom-right" } +}); + +MBGL_DEFINE_ENUM(TextJustifyType, { + { TextJustifyType::Center, "center" }, + { TextJustifyType::Left, "left" }, + { TextJustifyType::Right, "right" }, +}); + +MBGL_DEFINE_ENUM(TextTransformType, { + { TextTransformType::None, "none" }, + { TextTransformType::Uppercase, "uppercase" }, + { TextTransformType::Lowercase, "lowercase" }, +}); + +MBGL_DEFINE_ENUM(RotationAlignmentType, { + { RotationAlignmentType::Map, "map" }, + { RotationAlignmentType::Viewport, "viewport" }, +}); + +} diff --git a/test/src/mbgl/test/fixture_log_observer.cpp b/test/src/mbgl/test/fixture_log_observer.cpp index 302fdc70816..8ab6e00f53c 100644 --- a/test/src/mbgl/test/fixture_log_observer.cpp +++ b/test/src/mbgl/test/fixture_log_observer.cpp @@ -1,5 +1,6 @@ #include #include +#include namespace mbgl { @@ -96,7 +97,8 @@ ::std::ostream& operator<<(::std::ostream& os, const std::vector::toString(message.severity) << "\", \""; + os << Enum::toString(message.event) << "\""; os << ", " << message.code; os << ", \"" << message.msg << "\""; return os << "]" << std::endl; diff --git a/test/style/style_parser.cpp b/test/style/style_parser.cpp index 5f730a8373d..bc9ca9f24c5 100644 --- a/test/style/style_parser.cpp +++ b/test/style/style_parser.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -46,8 +47,8 @@ TEST_P(StyleParserTest, ParseStyle) { const uint32_t count = js_entry[rapidjson::SizeType(0)].GetUint(); const FixtureLogObserver::LogMessage message { - EventSeverityClass(js_entry[rapidjson::SizeType(1)].GetString()), - EventClass(js_entry[rapidjson::SizeType(2)].GetString()), + *Enum::toEnum(js_entry[rapidjson::SizeType(1)].GetString()), + *Enum::toEnum(js_entry[rapidjson::SizeType(2)].GetString()), int64_t(-1), js_entry[rapidjson::SizeType(3)].GetString() };