// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: dmi/hw_events_mgmt_service.proto

#ifndef PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
#define PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto

#include <limits>
#include <string>

#include <google/protobuf/port_def.inc>
#if PROTOBUF_VERSION < 3007000
#error This file was generated by a newer version of protoc which is
#error incompatible with your Protocol Buffer headers. Please update
#error your headers.
#endif
#if 3007000 < PROTOBUF_MIN_PROTOC_VERSION
#error This file was generated by an older version of protoc which is
#error incompatible with your Protocol Buffer headers. Please
#error regenerate this file with a newer version of protoc.
#endif

#include <google/protobuf/port_undef.inc>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/arena.h>
#include <google/protobuf/arenastring.h>
#include <google/protobuf/generated_message_table_driven.h>
#include <google/protobuf/generated_message_util.h>
#include <google/protobuf/inlined_string_field.h>
#include <google/protobuf/metadata.h>
#include <google/protobuf/message.h>
#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
#include <google/protobuf/extension_set.h>  // IWYU pragma: export
#include <google/protobuf/generated_enum_reflection.h>
#include <google/protobuf/unknown_field_set.h>
#include "dmi/commons.pb.h"
#include "dmi/hw.pb.h"
#include <google/protobuf/timestamp.pb.h>
#include <google/protobuf/empty.pb.h>
// @@protoc_insertion_point(includes)
#include <google/protobuf/port_def.inc>
#define PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto

// Internal implementation detail -- do not use these members.
struct TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto {
  static const ::google::protobuf::internal::ParseTableField entries[]
    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
  static const ::google::protobuf::internal::AuxillaryParseTableField aux[]
    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
  static const ::google::protobuf::internal::ParseTable schema[11]
    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
  static const ::google::protobuf::internal::FieldMetadata field_metadata[];
  static const ::google::protobuf::internal::SerializationTable serialization_table[];
  static const ::google::protobuf::uint32 offsets[];
};
void AddDescriptors_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto();
namespace dmi {
class Event;
class EventDefaultTypeInternal;
extern EventDefaultTypeInternal _Event_default_instance_;
class EventCfg;
class EventCfgDefaultTypeInternal;
extern EventCfgDefaultTypeInternal _EventCfg_default_instance_;
class EventMetaData;
class EventMetaDataDefaultTypeInternal;
extern EventMetaDataDefaultTypeInternal _EventMetaData_default_instance_;
class EventsCfg;
class EventsCfgDefaultTypeInternal;
extern EventsCfgDefaultTypeInternal _EventsCfg_default_instance_;
class EventsConfigurationRequest;
class EventsConfigurationRequestDefaultTypeInternal;
extern EventsConfigurationRequestDefaultTypeInternal _EventsConfigurationRequest_default_instance_;
class EventsConfigurationResponse;
class EventsConfigurationResponseDefaultTypeInternal;
extern EventsConfigurationResponseDefaultTypeInternal _EventsConfigurationResponse_default_instance_;
class ListEventsResponse;
class ListEventsResponseDefaultTypeInternal;
extern ListEventsResponseDefaultTypeInternal _ListEventsResponse_default_instance_;
class ThresholdInformation;
class ThresholdInformationDefaultTypeInternal;
extern ThresholdInformationDefaultTypeInternal _ThresholdInformation_default_instance_;
class Thresholds;
class ThresholdsDefaultTypeInternal;
extern ThresholdsDefaultTypeInternal _Thresholds_default_instance_;
class ValueType;
class ValueTypeDefaultTypeInternal;
extern ValueTypeDefaultTypeInternal _ValueType_default_instance_;
class WaterMarks;
class WaterMarksDefaultTypeInternal;
extern WaterMarksDefaultTypeInternal _WaterMarks_default_instance_;
}  // namespace dmi
namespace google {
namespace protobuf {
template<> ::dmi::Event* Arena::CreateMaybeMessage<::dmi::Event>(Arena*);
template<> ::dmi::EventCfg* Arena::CreateMaybeMessage<::dmi::EventCfg>(Arena*);
template<> ::dmi::EventMetaData* Arena::CreateMaybeMessage<::dmi::EventMetaData>(Arena*);
template<> ::dmi::EventsCfg* Arena::CreateMaybeMessage<::dmi::EventsCfg>(Arena*);
template<> ::dmi::EventsConfigurationRequest* Arena::CreateMaybeMessage<::dmi::EventsConfigurationRequest>(Arena*);
template<> ::dmi::EventsConfigurationResponse* Arena::CreateMaybeMessage<::dmi::EventsConfigurationResponse>(Arena*);
template<> ::dmi::ListEventsResponse* Arena::CreateMaybeMessage<::dmi::ListEventsResponse>(Arena*);
template<> ::dmi::ThresholdInformation* Arena::CreateMaybeMessage<::dmi::ThresholdInformation>(Arena*);
template<> ::dmi::Thresholds* Arena::CreateMaybeMessage<::dmi::Thresholds>(Arena*);
template<> ::dmi::ValueType* Arena::CreateMaybeMessage<::dmi::ValueType>(Arena*);
template<> ::dmi::WaterMarks* Arena::CreateMaybeMessage<::dmi::WaterMarks>(Arena*);
}  // namespace protobuf
}  // namespace google
namespace dmi {

enum ListEventsResponse_Reason {
  ListEventsResponse_Reason_UNDEFINED_REASON = 0,
  ListEventsResponse_Reason_UNKNOWN_DEVICE = 1,
  ListEventsResponse_Reason_INTERNAL_ERROR = 2,
  ListEventsResponse_Reason_DEVICE_UNREACHABLE = 3,
  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
  ListEventsResponse_Reason_ListEventsResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
};
bool ListEventsResponse_Reason_IsValid(int value);
const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MIN = ListEventsResponse_Reason_UNDEFINED_REASON;
const ListEventsResponse_Reason ListEventsResponse_Reason_Reason_MAX = ListEventsResponse_Reason_DEVICE_UNREACHABLE;
const int ListEventsResponse_Reason_Reason_ARRAYSIZE = ListEventsResponse_Reason_Reason_MAX + 1;

const ::google::protobuf::EnumDescriptor* ListEventsResponse_Reason_descriptor();
inline const ::std::string& ListEventsResponse_Reason_Name(ListEventsResponse_Reason value) {
  return ::google::protobuf::internal::NameOfEnum(
    ListEventsResponse_Reason_descriptor(), value);
}
inline bool ListEventsResponse_Reason_Parse(
    const ::std::string& name, ListEventsResponse_Reason* value) {
  return ::google::protobuf::internal::ParseNamedEnum<ListEventsResponse_Reason>(
    ListEventsResponse_Reason_descriptor(), name, value);
}
enum EventsConfigurationResponse_Reason {
  EventsConfigurationResponse_Reason_UNDEFINED_REASON = 0,
  EventsConfigurationResponse_Reason_UNKNOWN_DEVICE = 1,
  EventsConfigurationResponse_Reason_INTERNAL_ERROR = 2,
  EventsConfigurationResponse_Reason_INVALID_CONFIG = 3,
  EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE = 4,
  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
  EventsConfigurationResponse_Reason_EventsConfigurationResponse_Reason_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
};
bool EventsConfigurationResponse_Reason_IsValid(int value);
const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MIN = EventsConfigurationResponse_Reason_UNDEFINED_REASON;
const EventsConfigurationResponse_Reason EventsConfigurationResponse_Reason_Reason_MAX = EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
const int EventsConfigurationResponse_Reason_Reason_ARRAYSIZE = EventsConfigurationResponse_Reason_Reason_MAX + 1;

const ::google::protobuf::EnumDescriptor* EventsConfigurationResponse_Reason_descriptor();
inline const ::std::string& EventsConfigurationResponse_Reason_Name(EventsConfigurationResponse_Reason value) {
  return ::google::protobuf::internal::NameOfEnum(
    EventsConfigurationResponse_Reason_descriptor(), value);
}
inline bool EventsConfigurationResponse_Reason_Parse(
    const ::std::string& name, EventsConfigurationResponse_Reason* value) {
  return ::google::protobuf::internal::ParseNamedEnum<EventsConfigurationResponse_Reason>(
    EventsConfigurationResponse_Reason_descriptor(), name, value);
}
enum EventIds {
  EVENT_NAME_UNDEFINED = 0,
  EVENT_TRANSCEIVER_PLUG_OUT = 100,
  EVENT_TRANSCEIVER_PLUG_IN = 101,
  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD = 102,
  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD = 103,
  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD = 104,
  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD = 105,
  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD = 106,
  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD = 107,
  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD = 108,
  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD = 109,
  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD = 110,
  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD = 111,
  EVENT_TRANSCEIVER_FAILURE = 112,
  EVENT_TRANSCEIVER_VOLTAGE_ABOVE_THRESHOLD_RECOVERED = 113,
  EVENT_TRANSCEIVER_VOLTAGE_BELOW_THRESHOLD_RECOVERED = 114,
  EVENT_TRANSCEIVER_TEMPERATURE_ABOVE_THRESHOLD_RECOVERED = 115,
  EVENT_TRANSCEIVER_TEMPERATURE_BELOW_THRESHOLD_RECOVERED = 116,
  EVENT_TRANSCEIVER_CURRENT_ABOVE_THRESHOLD_RECOVERED = 117,
  EVENT_TRANSCEIVER_CURRENT_BELOW_THRESHOLD_RECOVERED = 118,
  EVENT_TRANSCEIVER_RX_POWER_ABOVE_THRESHOLD_RECOVERED = 119,
  EVENT_TRANSCEIVER_RX_POWER_BELOW_THRESHOLD_RECOVERED = 120,
  EVENT_TRANSCEIVER_TX_POWER_ABOVE_THRESHOLD_RECOVERED = 121,
  EVENT_TRANSCEIVER_TX_POWER_BELOW_THRESHOLD_RECOVERED = 122,
  EVENT_TRANSCEIVER_FAILURE_RECOVERED = 123,
  EVENT_PSU_PLUG_OUT = 200,
  EVENT_PSU_PLUG_IN = 201,
  EVENT_PSU_FAILURE = 202,
  EVENT_PSU_FAILURE_RECOVERED = 203,
  EVENT_FAN_FAILURE = 300,
  EVENT_FAN_PLUG_OUT = 301,
  EVENT_FAN_PLUG_IN = 302,
  EVENT_FAN_FAILURE_RECOVERED = 303,
  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL = 400,
  EVENT_CPU_TEMPERATURE_ABOVE_FATAL = 401,
  EVENT_CPU_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 402,
  EVENT_CPU_TEMPERATURE_ABOVE_FATAL_RECOVERED = 403,
  EVENT_HW_DEVICE_RESET = 500,
  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL = 501,
  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL = 502,
  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_CRITICAL_RECOVERED = 503,
  EVENT_HW_DEVICE_TEMPERATURE_ABOVE_FATAL_RECOVERED = 504,
  EVENT_HW_DEVICE_REBOOT = 505,
  EVENT_HW_TEMPERATURE_SENSOR_FAILED = 506,
  EVENT_HW_ALL_TEMPERATURE_SENSORS_FAILED = 507,
  EVENT_LINE_CARD_PLUG_OUT = 600,
  EVENT_LINE_CARD_PLUG_IN = 601,
  EventIds_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::min(),
  EventIds_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::google::protobuf::int32>::max()
};
bool EventIds_IsValid(int value);
const EventIds EventIds_MIN = EVENT_NAME_UNDEFINED;
const EventIds EventIds_MAX = EVENT_LINE_CARD_PLUG_IN;
const int EventIds_ARRAYSIZE = EventIds_MAX + 1;

const ::google::protobuf::EnumDescriptor* EventIds_descriptor();
inline const ::std::string& EventIds_Name(EventIds value) {
  return ::google::protobuf::internal::NameOfEnum(
    EventIds_descriptor(), value);
}
inline bool EventIds_Parse(
    const ::std::string& name, EventIds* value) {
  return ::google::protobuf::internal::ParseNamedEnum<EventIds>(
    EventIds_descriptor(), name, value);
}
// ===================================================================

class ValueType final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ValueType) */ {
 public:
  ValueType();
  virtual ~ValueType();

  ValueType(const ValueType& from);

  inline ValueType& operator=(const ValueType& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  ValueType(ValueType&& from) noexcept
    : ValueType() {
    *this = ::std::move(from);
  }

  inline ValueType& operator=(ValueType&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const ValueType& default_instance();

  enum ValCase {
    kIntVal = 1,
    kUintVal = 2,
    kFloatVal = 3,
    VAL_NOT_SET = 0,
  };

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const ValueType* internal_default_instance() {
    return reinterpret_cast<const ValueType*>(
               &_ValueType_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    0;

  void Swap(ValueType* other);
  friend void swap(ValueType& a, ValueType& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline ValueType* New() const final {
    return CreateMaybeMessage<ValueType>(nullptr);
  }

  ValueType* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<ValueType>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const ValueType& from);
  void MergeFrom(const ValueType& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(ValueType* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // int64 int_val = 1;
  private:
  bool has_int_val() const;
  public:
  void clear_int_val();
  static const int kIntValFieldNumber = 1;
  ::google::protobuf::int64 int_val() const;
  void set_int_val(::google::protobuf::int64 value);

  // uint64 uint_val = 2;
  private:
  bool has_uint_val() const;
  public:
  void clear_uint_val();
  static const int kUintValFieldNumber = 2;
  ::google::protobuf::uint64 uint_val() const;
  void set_uint_val(::google::protobuf::uint64 value);

  // float float_val = 3;
  private:
  bool has_float_val() const;
  public:
  void clear_float_val();
  static const int kFloatValFieldNumber = 3;
  float float_val() const;
  void set_float_val(float value);

  void clear_val();
  ValCase val_case() const;
  // @@protoc_insertion_point(class_scope:dmi.ValueType)
 private:
  class HasBitSetters;
  void set_has_int_val();
  void set_has_uint_val();
  void set_has_float_val();

  inline bool has_val() const;
  inline void clear_has_val();

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  union ValUnion {
    ValUnion() {}
    ::google::protobuf::int64 int_val_;
    ::google::protobuf::uint64 uint_val_;
    float float_val_;
  } val_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  ::google::protobuf::uint32 _oneof_case_[1];

  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class WaterMarks final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.WaterMarks) */ {
 public:
  WaterMarks();
  virtual ~WaterMarks();

  WaterMarks(const WaterMarks& from);

  inline WaterMarks& operator=(const WaterMarks& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  WaterMarks(WaterMarks&& from) noexcept
    : WaterMarks() {
    *this = ::std::move(from);
  }

  inline WaterMarks& operator=(WaterMarks&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const WaterMarks& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const WaterMarks* internal_default_instance() {
    return reinterpret_cast<const WaterMarks*>(
               &_WaterMarks_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    1;

  void Swap(WaterMarks* other);
  friend void swap(WaterMarks& a, WaterMarks& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline WaterMarks* New() const final {
    return CreateMaybeMessage<WaterMarks>(nullptr);
  }

  WaterMarks* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<WaterMarks>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const WaterMarks& from);
  void MergeFrom(const WaterMarks& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(WaterMarks* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // .dmi.ValueType high = 1;
  bool has_high() const;
  void clear_high();
  static const int kHighFieldNumber = 1;
  const ::dmi::ValueType& high() const;
  ::dmi::ValueType* release_high();
  ::dmi::ValueType* mutable_high();
  void set_allocated_high(::dmi::ValueType* high);

  // .dmi.ValueType low = 2;
  bool has_low() const;
  void clear_low();
  static const int kLowFieldNumber = 2;
  const ::dmi::ValueType& low() const;
  ::dmi::ValueType* release_low();
  ::dmi::ValueType* mutable_low();
  void set_allocated_low(::dmi::ValueType* low);

  // @@protoc_insertion_point(class_scope:dmi.WaterMarks)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::dmi::ValueType* high_;
  ::dmi::ValueType* low_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class Thresholds final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Thresholds) */ {
 public:
  Thresholds();
  virtual ~Thresholds();

  Thresholds(const Thresholds& from);

  inline Thresholds& operator=(const Thresholds& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  Thresholds(Thresholds&& from) noexcept
    : Thresholds() {
    *this = ::std::move(from);
  }

  inline Thresholds& operator=(Thresholds&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const Thresholds& default_instance();

  enum ThresholdCase {
    kUpper = 1,
    kLower = 2,
    THRESHOLD_NOT_SET = 0,
  };

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const Thresholds* internal_default_instance() {
    return reinterpret_cast<const Thresholds*>(
               &_Thresholds_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    2;

  void Swap(Thresholds* other);
  friend void swap(Thresholds& a, Thresholds& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline Thresholds* New() const final {
    return CreateMaybeMessage<Thresholds>(nullptr);
  }

  Thresholds* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<Thresholds>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const Thresholds& from);
  void MergeFrom(const Thresholds& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(Thresholds* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // .dmi.WaterMarks upper = 1;
  bool has_upper() const;
  void clear_upper();
  static const int kUpperFieldNumber = 1;
  const ::dmi::WaterMarks& upper() const;
  ::dmi::WaterMarks* release_upper();
  ::dmi::WaterMarks* mutable_upper();
  void set_allocated_upper(::dmi::WaterMarks* upper);

  // .dmi.WaterMarks lower = 2;
  bool has_lower() const;
  void clear_lower();
  static const int kLowerFieldNumber = 2;
  const ::dmi::WaterMarks& lower() const;
  ::dmi::WaterMarks* release_lower();
  ::dmi::WaterMarks* mutable_lower();
  void set_allocated_lower(::dmi::WaterMarks* lower);

  void clear_threshold();
  ThresholdCase threshold_case() const;
  // @@protoc_insertion_point(class_scope:dmi.Thresholds)
 private:
  class HasBitSetters;
  void set_has_upper();
  void set_has_lower();

  inline bool has_threshold() const;
  inline void clear_has_threshold();

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  union ThresholdUnion {
    ThresholdUnion() {}
    ::dmi::WaterMarks* upper_;
    ::dmi::WaterMarks* lower_;
  } threshold_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  ::google::protobuf::uint32 _oneof_case_[1];

  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class ThresholdInformation final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ThresholdInformation) */ {
 public:
  ThresholdInformation();
  virtual ~ThresholdInformation();

  ThresholdInformation(const ThresholdInformation& from);

  inline ThresholdInformation& operator=(const ThresholdInformation& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  ThresholdInformation(ThresholdInformation&& from) noexcept
    : ThresholdInformation() {
    *this = ::std::move(from);
  }

  inline ThresholdInformation& operator=(ThresholdInformation&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const ThresholdInformation& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const ThresholdInformation* internal_default_instance() {
    return reinterpret_cast<const ThresholdInformation*>(
               &_ThresholdInformation_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    3;

  void Swap(ThresholdInformation* other);
  friend void swap(ThresholdInformation& a, ThresholdInformation& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline ThresholdInformation* New() const final {
    return CreateMaybeMessage<ThresholdInformation>(nullptr);
  }

  ThresholdInformation* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<ThresholdInformation>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const ThresholdInformation& from);
  void MergeFrom(const ThresholdInformation& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(ThresholdInformation* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // .dmi.ValueType observed_value = 1;
  bool has_observed_value() const;
  void clear_observed_value();
  static const int kObservedValueFieldNumber = 1;
  const ::dmi::ValueType& observed_value() const;
  ::dmi::ValueType* release_observed_value();
  ::dmi::ValueType* mutable_observed_value();
  void set_allocated_observed_value(::dmi::ValueType* observed_value);

  // .dmi.Thresholds thresholds = 2;
  bool has_thresholds() const;
  void clear_thresholds();
  static const int kThresholdsFieldNumber = 2;
  const ::dmi::Thresholds& thresholds() const;
  ::dmi::Thresholds* release_thresholds();
  ::dmi::Thresholds* mutable_thresholds();
  void set_allocated_thresholds(::dmi::Thresholds* thresholds);

  // @@protoc_insertion_point(class_scope:dmi.ThresholdInformation)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::dmi::ValueType* observed_value_;
  ::dmi::Thresholds* thresholds_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class EventCfg final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventCfg) */ {
 public:
  EventCfg();
  virtual ~EventCfg();

  EventCfg(const EventCfg& from);

  inline EventCfg& operator=(const EventCfg& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  EventCfg(EventCfg&& from) noexcept
    : EventCfg() {
    *this = ::std::move(from);
  }

  inline EventCfg& operator=(EventCfg&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const EventCfg& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const EventCfg* internal_default_instance() {
    return reinterpret_cast<const EventCfg*>(
               &_EventCfg_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    4;

  void Swap(EventCfg* other);
  friend void swap(EventCfg& a, EventCfg& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline EventCfg* New() const final {
    return CreateMaybeMessage<EventCfg>(nullptr);
  }

  EventCfg* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<EventCfg>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const EventCfg& from);
  void MergeFrom(const EventCfg& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(EventCfg* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // .dmi.Thresholds thresholds = 3;
  bool has_thresholds() const;
  void clear_thresholds();
  static const int kThresholdsFieldNumber = 3;
  const ::dmi::Thresholds& thresholds() const;
  ::dmi::Thresholds* release_thresholds();
  ::dmi::Thresholds* mutable_thresholds();
  void set_allocated_thresholds(::dmi::Thresholds* thresholds);

  // .dmi.EventIds event_id = 1;
  void clear_event_id();
  static const int kEventIdFieldNumber = 1;
  ::dmi::EventIds event_id() const;
  void set_event_id(::dmi::EventIds value);

  // bool is_configured = 2;
  void clear_is_configured();
  static const int kIsConfiguredFieldNumber = 2;
  bool is_configured() const;
  void set_is_configured(bool value);

  // @@protoc_insertion_point(class_scope:dmi.EventCfg)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::dmi::Thresholds* thresholds_;
  int event_id_;
  bool is_configured_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class EventsCfg final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsCfg) */ {
 public:
  EventsCfg();
  virtual ~EventsCfg();

  EventsCfg(const EventsCfg& from);

  inline EventsCfg& operator=(const EventsCfg& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  EventsCfg(EventsCfg&& from) noexcept
    : EventsCfg() {
    *this = ::std::move(from);
  }

  inline EventsCfg& operator=(EventsCfg&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const EventsCfg& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const EventsCfg* internal_default_instance() {
    return reinterpret_cast<const EventsCfg*>(
               &_EventsCfg_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    5;

  void Swap(EventsCfg* other);
  friend void swap(EventsCfg& a, EventsCfg& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline EventsCfg* New() const final {
    return CreateMaybeMessage<EventsCfg>(nullptr);
  }

  EventsCfg* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<EventsCfg>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const EventsCfg& from);
  void MergeFrom(const EventsCfg& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(EventsCfg* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // repeated .dmi.EventCfg items = 1;
  int items_size() const;
  void clear_items();
  static const int kItemsFieldNumber = 1;
  ::dmi::EventCfg* mutable_items(int index);
  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
      mutable_items();
  const ::dmi::EventCfg& items(int index) const;
  ::dmi::EventCfg* add_items();
  const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
      items() const;

  // @@protoc_insertion_point(class_scope:dmi.EventsCfg)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg > items_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class ListEventsResponse final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.ListEventsResponse) */ {
 public:
  ListEventsResponse();
  virtual ~ListEventsResponse();

  ListEventsResponse(const ListEventsResponse& from);

  inline ListEventsResponse& operator=(const ListEventsResponse& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  ListEventsResponse(ListEventsResponse&& from) noexcept
    : ListEventsResponse() {
    *this = ::std::move(from);
  }

  inline ListEventsResponse& operator=(ListEventsResponse&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const ListEventsResponse& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const ListEventsResponse* internal_default_instance() {
    return reinterpret_cast<const ListEventsResponse*>(
               &_ListEventsResponse_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    6;

  void Swap(ListEventsResponse* other);
  friend void swap(ListEventsResponse& a, ListEventsResponse& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline ListEventsResponse* New() const final {
    return CreateMaybeMessage<ListEventsResponse>(nullptr);
  }

  ListEventsResponse* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<ListEventsResponse>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const ListEventsResponse& from);
  void MergeFrom(const ListEventsResponse& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(ListEventsResponse* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  typedef ListEventsResponse_Reason Reason;
  static const Reason UNDEFINED_REASON =
    ListEventsResponse_Reason_UNDEFINED_REASON;
  static const Reason UNKNOWN_DEVICE =
    ListEventsResponse_Reason_UNKNOWN_DEVICE;
  static const Reason INTERNAL_ERROR =
    ListEventsResponse_Reason_INTERNAL_ERROR;
  static const Reason DEVICE_UNREACHABLE =
    ListEventsResponse_Reason_DEVICE_UNREACHABLE;
  static inline bool Reason_IsValid(int value) {
    return ListEventsResponse_Reason_IsValid(value);
  }
  static const Reason Reason_MIN =
    ListEventsResponse_Reason_Reason_MIN;
  static const Reason Reason_MAX =
    ListEventsResponse_Reason_Reason_MAX;
  static const int Reason_ARRAYSIZE =
    ListEventsResponse_Reason_Reason_ARRAYSIZE;
  static inline const ::google::protobuf::EnumDescriptor*
  Reason_descriptor() {
    return ListEventsResponse_Reason_descriptor();
  }
  static inline const ::std::string& Reason_Name(Reason value) {
    return ListEventsResponse_Reason_Name(value);
  }
  static inline bool Reason_Parse(const ::std::string& name,
      Reason* value) {
    return ListEventsResponse_Reason_Parse(name, value);
  }

  // accessors -------------------------------------------------------

  // string reason_detail = 4;
  void clear_reason_detail();
  static const int kReasonDetailFieldNumber = 4;
  const ::std::string& reason_detail() const;
  void set_reason_detail(const ::std::string& value);
  #if LANG_CXX11
  void set_reason_detail(::std::string&& value);
  #endif
  void set_reason_detail(const char* value);
  void set_reason_detail(const char* value, size_t size);
  ::std::string* mutable_reason_detail();
  ::std::string* release_reason_detail();
  void set_allocated_reason_detail(::std::string* reason_detail);

  // .dmi.EventsCfg events = 3;
  bool has_events() const;
  void clear_events();
  static const int kEventsFieldNumber = 3;
  const ::dmi::EventsCfg& events() const;
  ::dmi::EventsCfg* release_events();
  ::dmi::EventsCfg* mutable_events();
  void set_allocated_events(::dmi::EventsCfg* events);

  // .dmi.Status status = 1;
  void clear_status();
  static const int kStatusFieldNumber = 1;
  ::dmi::Status status() const;
  void set_status(::dmi::Status value);

  // .dmi.ListEventsResponse.Reason reason = 2;
  void clear_reason();
  static const int kReasonFieldNumber = 2;
  ::dmi::ListEventsResponse_Reason reason() const;
  void set_reason(::dmi::ListEventsResponse_Reason value);

  // @@protoc_insertion_point(class_scope:dmi.ListEventsResponse)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
  ::dmi::EventsCfg* events_;
  int status_;
  int reason_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class EventsConfigurationRequest final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationRequest) */ {
 public:
  EventsConfigurationRequest();
  virtual ~EventsConfigurationRequest();

  EventsConfigurationRequest(const EventsConfigurationRequest& from);

  inline EventsConfigurationRequest& operator=(const EventsConfigurationRequest& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  EventsConfigurationRequest(EventsConfigurationRequest&& from) noexcept
    : EventsConfigurationRequest() {
    *this = ::std::move(from);
  }

  inline EventsConfigurationRequest& operator=(EventsConfigurationRequest&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const EventsConfigurationRequest& default_instance();

  enum OperationCase {
    kChanges = 2,
    kResetToDefault = 3,
    OPERATION_NOT_SET = 0,
  };

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const EventsConfigurationRequest* internal_default_instance() {
    return reinterpret_cast<const EventsConfigurationRequest*>(
               &_EventsConfigurationRequest_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    7;

  void Swap(EventsConfigurationRequest* other);
  friend void swap(EventsConfigurationRequest& a, EventsConfigurationRequest& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline EventsConfigurationRequest* New() const final {
    return CreateMaybeMessage<EventsConfigurationRequest>(nullptr);
  }

  EventsConfigurationRequest* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<EventsConfigurationRequest>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const EventsConfigurationRequest& from);
  void MergeFrom(const EventsConfigurationRequest& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(EventsConfigurationRequest* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // .dmi.Uuid device_uuid = 1;
  bool has_device_uuid() const;
  void clear_device_uuid();
  static const int kDeviceUuidFieldNumber = 1;
  const ::dmi::Uuid& device_uuid() const;
  ::dmi::Uuid* release_device_uuid();
  ::dmi::Uuid* mutable_device_uuid();
  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);

  // .dmi.Uuid component_uuid = 4;
  bool has_component_uuid() const;
  void clear_component_uuid();
  static const int kComponentUuidFieldNumber = 4;
  const ::dmi::Uuid& component_uuid() const;
  ::dmi::Uuid* release_component_uuid();
  ::dmi::Uuid* mutable_component_uuid();
  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);

  // .dmi.EventsCfg changes = 2;
  bool has_changes() const;
  void clear_changes();
  static const int kChangesFieldNumber = 2;
  const ::dmi::EventsCfg& changes() const;
  ::dmi::EventsCfg* release_changes();
  ::dmi::EventsCfg* mutable_changes();
  void set_allocated_changes(::dmi::EventsCfg* changes);

  // bool reset_to_default = 3;
  private:
  bool has_reset_to_default() const;
  public:
  void clear_reset_to_default();
  static const int kResetToDefaultFieldNumber = 3;
  bool reset_to_default() const;
  void set_reset_to_default(bool value);

  void clear_operation();
  OperationCase operation_case() const;
  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationRequest)
 private:
  class HasBitSetters;
  void set_has_changes();
  void set_has_reset_to_default();

  inline bool has_operation() const;
  inline void clear_has_operation();

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::dmi::Uuid* device_uuid_;
  ::dmi::Uuid* component_uuid_;
  union OperationUnion {
    OperationUnion() {}
    ::dmi::EventsCfg* changes_;
    bool reset_to_default_;
  } operation_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  ::google::protobuf::uint32 _oneof_case_[1];

  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class EventsConfigurationResponse final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventsConfigurationResponse) */ {
 public:
  EventsConfigurationResponse();
  virtual ~EventsConfigurationResponse();

  EventsConfigurationResponse(const EventsConfigurationResponse& from);

  inline EventsConfigurationResponse& operator=(const EventsConfigurationResponse& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  EventsConfigurationResponse(EventsConfigurationResponse&& from) noexcept
    : EventsConfigurationResponse() {
    *this = ::std::move(from);
  }

  inline EventsConfigurationResponse& operator=(EventsConfigurationResponse&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const EventsConfigurationResponse& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const EventsConfigurationResponse* internal_default_instance() {
    return reinterpret_cast<const EventsConfigurationResponse*>(
               &_EventsConfigurationResponse_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    8;

  void Swap(EventsConfigurationResponse* other);
  friend void swap(EventsConfigurationResponse& a, EventsConfigurationResponse& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline EventsConfigurationResponse* New() const final {
    return CreateMaybeMessage<EventsConfigurationResponse>(nullptr);
  }

  EventsConfigurationResponse* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<EventsConfigurationResponse>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const EventsConfigurationResponse& from);
  void MergeFrom(const EventsConfigurationResponse& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(EventsConfigurationResponse* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  typedef EventsConfigurationResponse_Reason Reason;
  static const Reason UNDEFINED_REASON =
    EventsConfigurationResponse_Reason_UNDEFINED_REASON;
  static const Reason UNKNOWN_DEVICE =
    EventsConfigurationResponse_Reason_UNKNOWN_DEVICE;
  static const Reason INTERNAL_ERROR =
    EventsConfigurationResponse_Reason_INTERNAL_ERROR;
  static const Reason INVALID_CONFIG =
    EventsConfigurationResponse_Reason_INVALID_CONFIG;
  static const Reason DEVICE_UNREACHABLE =
    EventsConfigurationResponse_Reason_DEVICE_UNREACHABLE;
  static inline bool Reason_IsValid(int value) {
    return EventsConfigurationResponse_Reason_IsValid(value);
  }
  static const Reason Reason_MIN =
    EventsConfigurationResponse_Reason_Reason_MIN;
  static const Reason Reason_MAX =
    EventsConfigurationResponse_Reason_Reason_MAX;
  static const int Reason_ARRAYSIZE =
    EventsConfigurationResponse_Reason_Reason_ARRAYSIZE;
  static inline const ::google::protobuf::EnumDescriptor*
  Reason_descriptor() {
    return EventsConfigurationResponse_Reason_descriptor();
  }
  static inline const ::std::string& Reason_Name(Reason value) {
    return EventsConfigurationResponse_Reason_Name(value);
  }
  static inline bool Reason_Parse(const ::std::string& name,
      Reason* value) {
    return EventsConfigurationResponse_Reason_Parse(name, value);
  }

  // accessors -------------------------------------------------------

  // string reason_detail = 3;
  void clear_reason_detail();
  static const int kReasonDetailFieldNumber = 3;
  const ::std::string& reason_detail() const;
  void set_reason_detail(const ::std::string& value);
  #if LANG_CXX11
  void set_reason_detail(::std::string&& value);
  #endif
  void set_reason_detail(const char* value);
  void set_reason_detail(const char* value, size_t size);
  ::std::string* mutable_reason_detail();
  ::std::string* release_reason_detail();
  void set_allocated_reason_detail(::std::string* reason_detail);

  // .dmi.Status status = 1;
  void clear_status();
  static const int kStatusFieldNumber = 1;
  ::dmi::Status status() const;
  void set_status(::dmi::Status value);

  // .dmi.EventsConfigurationResponse.Reason reason = 2;
  void clear_reason();
  static const int kReasonFieldNumber = 2;
  ::dmi::EventsConfigurationResponse_Reason reason() const;
  void set_reason(::dmi::EventsConfigurationResponse_Reason value);

  // @@protoc_insertion_point(class_scope:dmi.EventsConfigurationResponse)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::google::protobuf::internal::ArenaStringPtr reason_detail_;
  int status_;
  int reason_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class EventMetaData final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.EventMetaData) */ {
 public:
  EventMetaData();
  virtual ~EventMetaData();

  EventMetaData(const EventMetaData& from);

  inline EventMetaData& operator=(const EventMetaData& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  EventMetaData(EventMetaData&& from) noexcept
    : EventMetaData() {
    *this = ::std::move(from);
  }

  inline EventMetaData& operator=(EventMetaData&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const EventMetaData& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const EventMetaData* internal_default_instance() {
    return reinterpret_cast<const EventMetaData*>(
               &_EventMetaData_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    9;

  void Swap(EventMetaData* other);
  friend void swap(EventMetaData& a, EventMetaData& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline EventMetaData* New() const final {
    return CreateMaybeMessage<EventMetaData>(nullptr);
  }

  EventMetaData* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<EventMetaData>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const EventMetaData& from);
  void MergeFrom(const EventMetaData& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(EventMetaData* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // string component_name = 3;
  void clear_component_name();
  static const int kComponentNameFieldNumber = 3;
  const ::std::string& component_name() const;
  void set_component_name(const ::std::string& value);
  #if LANG_CXX11
  void set_component_name(::std::string&& value);
  #endif
  void set_component_name(const char* value);
  void set_component_name(const char* value, size_t size);
  ::std::string* mutable_component_name();
  ::std::string* release_component_name();
  void set_allocated_component_name(::std::string* component_name);

  // .dmi.Uuid device_uuid = 1;
  bool has_device_uuid() const;
  void clear_device_uuid();
  static const int kDeviceUuidFieldNumber = 1;
  const ::dmi::Uuid& device_uuid() const;
  ::dmi::Uuid* release_device_uuid();
  ::dmi::Uuid* mutable_device_uuid();
  void set_allocated_device_uuid(::dmi::Uuid* device_uuid);

  // .dmi.Uuid component_uuid = 2;
  bool has_component_uuid() const;
  void clear_component_uuid();
  static const int kComponentUuidFieldNumber = 2;
  const ::dmi::Uuid& component_uuid() const;
  ::dmi::Uuid* release_component_uuid();
  ::dmi::Uuid* mutable_component_uuid();
  void set_allocated_component_uuid(::dmi::Uuid* component_uuid);

  // @@protoc_insertion_point(class_scope:dmi.EventMetaData)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::google::protobuf::internal::ArenaStringPtr component_name_;
  ::dmi::Uuid* device_uuid_;
  ::dmi::Uuid* component_uuid_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// -------------------------------------------------------------------

class Event final :
    public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:dmi.Event) */ {
 public:
  Event();
  virtual ~Event();

  Event(const Event& from);

  inline Event& operator=(const Event& from) {
    CopyFrom(from);
    return *this;
  }
  #if LANG_CXX11
  Event(Event&& from) noexcept
    : Event() {
    *this = ::std::move(from);
  }

  inline Event& operator=(Event&& from) noexcept {
    if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) {
      if (this != &from) InternalSwap(&from);
    } else {
      CopyFrom(from);
    }
    return *this;
  }
  #endif
  static const ::google::protobuf::Descriptor* descriptor() {
    return default_instance().GetDescriptor();
  }
  static const Event& default_instance();

  static void InitAsDefaultInstance();  // FOR INTERNAL USE ONLY
  static inline const Event* internal_default_instance() {
    return reinterpret_cast<const Event*>(
               &_Event_default_instance_);
  }
  static constexpr int kIndexInFileMessages =
    10;

  void Swap(Event* other);
  friend void swap(Event& a, Event& b) {
    a.Swap(&b);
  }

  // implements Message ----------------------------------------------

  inline Event* New() const final {
    return CreateMaybeMessage<Event>(nullptr);
  }

  Event* New(::google::protobuf::Arena* arena) const final {
    return CreateMaybeMessage<Event>(arena);
  }
  void CopyFrom(const ::google::protobuf::Message& from) final;
  void MergeFrom(const ::google::protobuf::Message& from) final;
  void CopyFrom(const Event& from);
  void MergeFrom(const Event& from);
  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
  bool IsInitialized() const final;

  size_t ByteSizeLong() const final;
  #if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  static const char* _InternalParse(const char* begin, const char* end, void* object, ::google::protobuf::internal::ParseContext* ctx);
  ::google::protobuf::internal::ParseFunc _ParseFunc() const final { return _InternalParse; }
  #else
  bool MergePartialFromCodedStream(
      ::google::protobuf::io::CodedInputStream* input) final;
  #endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
  void SerializeWithCachedSizes(
      ::google::protobuf::io::CodedOutputStream* output) const final;
  ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray(
      ::google::protobuf::uint8* target) const final;
  int GetCachedSize() const final { return _cached_size_.Get(); }

  private:
  void SharedCtor();
  void SharedDtor();
  void SetCachedSize(int size) const final;
  void InternalSwap(Event* other);
  private:
  inline ::google::protobuf::Arena* GetArenaNoVirtual() const {
    return nullptr;
  }
  inline void* MaybeArenaPtr() const {
    return nullptr;
  }
  public:

  ::google::protobuf::Metadata GetMetadata() const final;

  // nested types ----------------------------------------------------

  // accessors -------------------------------------------------------

  // string add_info = 5;
  void clear_add_info();
  static const int kAddInfoFieldNumber = 5;
  const ::std::string& add_info() const;
  void set_add_info(const ::std::string& value);
  #if LANG_CXX11
  void set_add_info(::std::string&& value);
  #endif
  void set_add_info(const char* value);
  void set_add_info(const char* value, size_t size);
  ::std::string* mutable_add_info();
  ::std::string* release_add_info();
  void set_allocated_add_info(::std::string* add_info);

  // .dmi.EventMetaData event_metadata = 1;
  bool has_event_metadata() const;
  void clear_event_metadata();
  static const int kEventMetadataFieldNumber = 1;
  const ::dmi::EventMetaData& event_metadata() const;
  ::dmi::EventMetaData* release_event_metadata();
  ::dmi::EventMetaData* mutable_event_metadata();
  void set_allocated_event_metadata(::dmi::EventMetaData* event_metadata);

  // .google.protobuf.Timestamp raised_ts = 3;
  bool has_raised_ts() const;
  void clear_raised_ts();
  static const int kRaisedTsFieldNumber = 3;
  const ::google::protobuf::Timestamp& raised_ts() const;
  ::google::protobuf::Timestamp* release_raised_ts();
  ::google::protobuf::Timestamp* mutable_raised_ts();
  void set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts);

  // .dmi.ThresholdInformation threshold_info = 4;
  bool has_threshold_info() const;
  void clear_threshold_info();
  static const int kThresholdInfoFieldNumber = 4;
  const ::dmi::ThresholdInformation& threshold_info() const;
  ::dmi::ThresholdInformation* release_threshold_info();
  ::dmi::ThresholdInformation* mutable_threshold_info();
  void set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info);

  // .dmi.EventIds event_id = 2;
  void clear_event_id();
  static const int kEventIdFieldNumber = 2;
  ::dmi::EventIds event_id() const;
  void set_event_id(::dmi::EventIds value);

  // @@protoc_insertion_point(class_scope:dmi.Event)
 private:
  class HasBitSetters;

  ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_;
  ::google::protobuf::internal::ArenaStringPtr add_info_;
  ::dmi::EventMetaData* event_metadata_;
  ::google::protobuf::Timestamp* raised_ts_;
  ::dmi::ThresholdInformation* threshold_info_;
  int event_id_;
  mutable ::google::protobuf::internal::CachedSize _cached_size_;
  friend struct ::TableStruct_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto;
};
// ===================================================================


// ===================================================================

#ifdef __GNUC__
  #pragma GCC diagnostic push
  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif  // __GNUC__
// ValueType

// int64 int_val = 1;
inline bool ValueType::has_int_val() const {
  return val_case() == kIntVal;
}
inline void ValueType::set_has_int_val() {
  _oneof_case_[0] = kIntVal;
}
inline void ValueType::clear_int_val() {
  if (has_int_val()) {
    val_.int_val_ = PROTOBUF_LONGLONG(0);
    clear_has_val();
  }
}
inline ::google::protobuf::int64 ValueType::int_val() const {
  // @@protoc_insertion_point(field_get:dmi.ValueType.int_val)
  if (has_int_val()) {
    return val_.int_val_;
  }
  return PROTOBUF_LONGLONG(0);
}
inline void ValueType::set_int_val(::google::protobuf::int64 value) {
  if (!has_int_val()) {
    clear_val();
    set_has_int_val();
  }
  val_.int_val_ = value;
  // @@protoc_insertion_point(field_set:dmi.ValueType.int_val)
}

// uint64 uint_val = 2;
inline bool ValueType::has_uint_val() const {
  return val_case() == kUintVal;
}
inline void ValueType::set_has_uint_val() {
  _oneof_case_[0] = kUintVal;
}
inline void ValueType::clear_uint_val() {
  if (has_uint_val()) {
    val_.uint_val_ = PROTOBUF_ULONGLONG(0);
    clear_has_val();
  }
}
inline ::google::protobuf::uint64 ValueType::uint_val() const {
  // @@protoc_insertion_point(field_get:dmi.ValueType.uint_val)
  if (has_uint_val()) {
    return val_.uint_val_;
  }
  return PROTOBUF_ULONGLONG(0);
}
inline void ValueType::set_uint_val(::google::protobuf::uint64 value) {
  if (!has_uint_val()) {
    clear_val();
    set_has_uint_val();
  }
  val_.uint_val_ = value;
  // @@protoc_insertion_point(field_set:dmi.ValueType.uint_val)
}

// float float_val = 3;
inline bool ValueType::has_float_val() const {
  return val_case() == kFloatVal;
}
inline void ValueType::set_has_float_val() {
  _oneof_case_[0] = kFloatVal;
}
inline void ValueType::clear_float_val() {
  if (has_float_val()) {
    val_.float_val_ = 0;
    clear_has_val();
  }
}
inline float ValueType::float_val() const {
  // @@protoc_insertion_point(field_get:dmi.ValueType.float_val)
  if (has_float_val()) {
    return val_.float_val_;
  }
  return 0;
}
inline void ValueType::set_float_val(float value) {
  if (!has_float_val()) {
    clear_val();
    set_has_float_val();
  }
  val_.float_val_ = value;
  // @@protoc_insertion_point(field_set:dmi.ValueType.float_val)
}

inline bool ValueType::has_val() const {
  return val_case() != VAL_NOT_SET;
}
inline void ValueType::clear_has_val() {
  _oneof_case_[0] = VAL_NOT_SET;
}
inline ValueType::ValCase ValueType::val_case() const {
  return ValueType::ValCase(_oneof_case_[0]);
}
// -------------------------------------------------------------------

// WaterMarks

// .dmi.ValueType high = 1;
inline bool WaterMarks::has_high() const {
  return this != internal_default_instance() && high_ != nullptr;
}
inline void WaterMarks::clear_high() {
  if (GetArenaNoVirtual() == nullptr && high_ != nullptr) {
    delete high_;
  }
  high_ = nullptr;
}
inline const ::dmi::ValueType& WaterMarks::high() const {
  const ::dmi::ValueType* p = high_;
  // @@protoc_insertion_point(field_get:dmi.WaterMarks.high)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
      &::dmi::_ValueType_default_instance_);
}
inline ::dmi::ValueType* WaterMarks::release_high() {
  // @@protoc_insertion_point(field_release:dmi.WaterMarks.high)
  
  ::dmi::ValueType* temp = high_;
  high_ = nullptr;
  return temp;
}
inline ::dmi::ValueType* WaterMarks::mutable_high() {
  
  if (high_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
    high_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.high)
  return high_;
}
inline void WaterMarks::set_allocated_high(::dmi::ValueType* high) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete high_;
  }
  if (high) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      high = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, high, submessage_arena);
    }
    
  } else {
    
  }
  high_ = high;
  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.high)
}

// .dmi.ValueType low = 2;
inline bool WaterMarks::has_low() const {
  return this != internal_default_instance() && low_ != nullptr;
}
inline void WaterMarks::clear_low() {
  if (GetArenaNoVirtual() == nullptr && low_ != nullptr) {
    delete low_;
  }
  low_ = nullptr;
}
inline const ::dmi::ValueType& WaterMarks::low() const {
  const ::dmi::ValueType* p = low_;
  // @@protoc_insertion_point(field_get:dmi.WaterMarks.low)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
      &::dmi::_ValueType_default_instance_);
}
inline ::dmi::ValueType* WaterMarks::release_low() {
  // @@protoc_insertion_point(field_release:dmi.WaterMarks.low)
  
  ::dmi::ValueType* temp = low_;
  low_ = nullptr;
  return temp;
}
inline ::dmi::ValueType* WaterMarks::mutable_low() {
  
  if (low_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
    low_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.WaterMarks.low)
  return low_;
}
inline void WaterMarks::set_allocated_low(::dmi::ValueType* low) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete low_;
  }
  if (low) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      low = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, low, submessage_arena);
    }
    
  } else {
    
  }
  low_ = low;
  // @@protoc_insertion_point(field_set_allocated:dmi.WaterMarks.low)
}

// -------------------------------------------------------------------

// Thresholds

// .dmi.WaterMarks upper = 1;
inline bool Thresholds::has_upper() const {
  return threshold_case() == kUpper;
}
inline void Thresholds::set_has_upper() {
  _oneof_case_[0] = kUpper;
}
inline void Thresholds::clear_upper() {
  if (has_upper()) {
    delete threshold_.upper_;
    clear_has_threshold();
  }
}
inline ::dmi::WaterMarks* Thresholds::release_upper() {
  // @@protoc_insertion_point(field_release:dmi.Thresholds.upper)
  if (has_upper()) {
    clear_has_threshold();
      ::dmi::WaterMarks* temp = threshold_.upper_;
    threshold_.upper_ = nullptr;
    return temp;
  } else {
    return nullptr;
  }
}
inline const ::dmi::WaterMarks& Thresholds::upper() const {
  // @@protoc_insertion_point(field_get:dmi.Thresholds.upper)
  return has_upper()
      ? *threshold_.upper_
      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
}
inline ::dmi::WaterMarks* Thresholds::mutable_upper() {
  if (!has_upper()) {
    clear_threshold();
    set_has_upper();
    threshold_.upper_ = CreateMaybeMessage< ::dmi::WaterMarks >(
        GetArenaNoVirtual());
  }
  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.upper)
  return threshold_.upper_;
}

// .dmi.WaterMarks lower = 2;
inline bool Thresholds::has_lower() const {
  return threshold_case() == kLower;
}
inline void Thresholds::set_has_lower() {
  _oneof_case_[0] = kLower;
}
inline void Thresholds::clear_lower() {
  if (has_lower()) {
    delete threshold_.lower_;
    clear_has_threshold();
  }
}
inline ::dmi::WaterMarks* Thresholds::release_lower() {
  // @@protoc_insertion_point(field_release:dmi.Thresholds.lower)
  if (has_lower()) {
    clear_has_threshold();
      ::dmi::WaterMarks* temp = threshold_.lower_;
    threshold_.lower_ = nullptr;
    return temp;
  } else {
    return nullptr;
  }
}
inline const ::dmi::WaterMarks& Thresholds::lower() const {
  // @@protoc_insertion_point(field_get:dmi.Thresholds.lower)
  return has_lower()
      ? *threshold_.lower_
      : *reinterpret_cast< ::dmi::WaterMarks*>(&::dmi::_WaterMarks_default_instance_);
}
inline ::dmi::WaterMarks* Thresholds::mutable_lower() {
  if (!has_lower()) {
    clear_threshold();
    set_has_lower();
    threshold_.lower_ = CreateMaybeMessage< ::dmi::WaterMarks >(
        GetArenaNoVirtual());
  }
  // @@protoc_insertion_point(field_mutable:dmi.Thresholds.lower)
  return threshold_.lower_;
}

inline bool Thresholds::has_threshold() const {
  return threshold_case() != THRESHOLD_NOT_SET;
}
inline void Thresholds::clear_has_threshold() {
  _oneof_case_[0] = THRESHOLD_NOT_SET;
}
inline Thresholds::ThresholdCase Thresholds::threshold_case() const {
  return Thresholds::ThresholdCase(_oneof_case_[0]);
}
// -------------------------------------------------------------------

// ThresholdInformation

// .dmi.ValueType observed_value = 1;
inline bool ThresholdInformation::has_observed_value() const {
  return this != internal_default_instance() && observed_value_ != nullptr;
}
inline void ThresholdInformation::clear_observed_value() {
  if (GetArenaNoVirtual() == nullptr && observed_value_ != nullptr) {
    delete observed_value_;
  }
  observed_value_ = nullptr;
}
inline const ::dmi::ValueType& ThresholdInformation::observed_value() const {
  const ::dmi::ValueType* p = observed_value_;
  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.observed_value)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ValueType*>(
      &::dmi::_ValueType_default_instance_);
}
inline ::dmi::ValueType* ThresholdInformation::release_observed_value() {
  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.observed_value)
  
  ::dmi::ValueType* temp = observed_value_;
  observed_value_ = nullptr;
  return temp;
}
inline ::dmi::ValueType* ThresholdInformation::mutable_observed_value() {
  
  if (observed_value_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::ValueType>(GetArenaNoVirtual());
    observed_value_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.observed_value)
  return observed_value_;
}
inline void ThresholdInformation::set_allocated_observed_value(::dmi::ValueType* observed_value) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete observed_value_;
  }
  if (observed_value) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      observed_value = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, observed_value, submessage_arena);
    }
    
  } else {
    
  }
  observed_value_ = observed_value;
  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.observed_value)
}

// .dmi.Thresholds thresholds = 2;
inline bool ThresholdInformation::has_thresholds() const {
  return this != internal_default_instance() && thresholds_ != nullptr;
}
inline void ThresholdInformation::clear_thresholds() {
  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
    delete thresholds_;
  }
  thresholds_ = nullptr;
}
inline const ::dmi::Thresholds& ThresholdInformation::thresholds() const {
  const ::dmi::Thresholds* p = thresholds_;
  // @@protoc_insertion_point(field_get:dmi.ThresholdInformation.thresholds)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
      &::dmi::_Thresholds_default_instance_);
}
inline ::dmi::Thresholds* ThresholdInformation::release_thresholds() {
  // @@protoc_insertion_point(field_release:dmi.ThresholdInformation.thresholds)
  
  ::dmi::Thresholds* temp = thresholds_;
  thresholds_ = nullptr;
  return temp;
}
inline ::dmi::Thresholds* ThresholdInformation::mutable_thresholds() {
  
  if (thresholds_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
    thresholds_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.ThresholdInformation.thresholds)
  return thresholds_;
}
inline void ThresholdInformation::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete thresholds_;
  }
  if (thresholds) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      thresholds = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, thresholds, submessage_arena);
    }
    
  } else {
    
  }
  thresholds_ = thresholds;
  // @@protoc_insertion_point(field_set_allocated:dmi.ThresholdInformation.thresholds)
}

// -------------------------------------------------------------------

// EventCfg

// .dmi.EventIds event_id = 1;
inline void EventCfg::clear_event_id() {
  event_id_ = 0;
}
inline ::dmi::EventIds EventCfg::event_id() const {
  // @@protoc_insertion_point(field_get:dmi.EventCfg.event_id)
  return static_cast< ::dmi::EventIds >(event_id_);
}
inline void EventCfg::set_event_id(::dmi::EventIds value) {
  
  event_id_ = value;
  // @@protoc_insertion_point(field_set:dmi.EventCfg.event_id)
}

// bool is_configured = 2;
inline void EventCfg::clear_is_configured() {
  is_configured_ = false;
}
inline bool EventCfg::is_configured() const {
  // @@protoc_insertion_point(field_get:dmi.EventCfg.is_configured)
  return is_configured_;
}
inline void EventCfg::set_is_configured(bool value) {
  
  is_configured_ = value;
  // @@protoc_insertion_point(field_set:dmi.EventCfg.is_configured)
}

// .dmi.Thresholds thresholds = 3;
inline bool EventCfg::has_thresholds() const {
  return this != internal_default_instance() && thresholds_ != nullptr;
}
inline void EventCfg::clear_thresholds() {
  if (GetArenaNoVirtual() == nullptr && thresholds_ != nullptr) {
    delete thresholds_;
  }
  thresholds_ = nullptr;
}
inline const ::dmi::Thresholds& EventCfg::thresholds() const {
  const ::dmi::Thresholds* p = thresholds_;
  // @@protoc_insertion_point(field_get:dmi.EventCfg.thresholds)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Thresholds*>(
      &::dmi::_Thresholds_default_instance_);
}
inline ::dmi::Thresholds* EventCfg::release_thresholds() {
  // @@protoc_insertion_point(field_release:dmi.EventCfg.thresholds)
  
  ::dmi::Thresholds* temp = thresholds_;
  thresholds_ = nullptr;
  return temp;
}
inline ::dmi::Thresholds* EventCfg::mutable_thresholds() {
  
  if (thresholds_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Thresholds>(GetArenaNoVirtual());
    thresholds_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventCfg.thresholds)
  return thresholds_;
}
inline void EventCfg::set_allocated_thresholds(::dmi::Thresholds* thresholds) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete thresholds_;
  }
  if (thresholds) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      thresholds = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, thresholds, submessage_arena);
    }
    
  } else {
    
  }
  thresholds_ = thresholds;
  // @@protoc_insertion_point(field_set_allocated:dmi.EventCfg.thresholds)
}

// -------------------------------------------------------------------

// EventsCfg

// repeated .dmi.EventCfg items = 1;
inline int EventsCfg::items_size() const {
  return items_.size();
}
inline void EventsCfg::clear_items() {
  items_.Clear();
}
inline ::dmi::EventCfg* EventsCfg::mutable_items(int index) {
  // @@protoc_insertion_point(field_mutable:dmi.EventsCfg.items)
  return items_.Mutable(index);
}
inline ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >*
EventsCfg::mutable_items() {
  // @@protoc_insertion_point(field_mutable_list:dmi.EventsCfg.items)
  return &items_;
}
inline const ::dmi::EventCfg& EventsCfg::items(int index) const {
  // @@protoc_insertion_point(field_get:dmi.EventsCfg.items)
  return items_.Get(index);
}
inline ::dmi::EventCfg* EventsCfg::add_items() {
  // @@protoc_insertion_point(field_add:dmi.EventsCfg.items)
  return items_.Add();
}
inline const ::google::protobuf::RepeatedPtrField< ::dmi::EventCfg >&
EventsCfg::items() const {
  // @@protoc_insertion_point(field_list:dmi.EventsCfg.items)
  return items_;
}

// -------------------------------------------------------------------

// ListEventsResponse

// .dmi.Status status = 1;
inline void ListEventsResponse::clear_status() {
  status_ = 0;
}
inline ::dmi::Status ListEventsResponse::status() const {
  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.status)
  return static_cast< ::dmi::Status >(status_);
}
inline void ListEventsResponse::set_status(::dmi::Status value) {
  
  status_ = value;
  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.status)
}

// .dmi.ListEventsResponse.Reason reason = 2;
inline void ListEventsResponse::clear_reason() {
  reason_ = 0;
}
inline ::dmi::ListEventsResponse_Reason ListEventsResponse::reason() const {
  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason)
  return static_cast< ::dmi::ListEventsResponse_Reason >(reason_);
}
inline void ListEventsResponse::set_reason(::dmi::ListEventsResponse_Reason value) {
  
  reason_ = value;
  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason)
}

// .dmi.EventsCfg events = 3;
inline bool ListEventsResponse::has_events() const {
  return this != internal_default_instance() && events_ != nullptr;
}
inline void ListEventsResponse::clear_events() {
  if (GetArenaNoVirtual() == nullptr && events_ != nullptr) {
    delete events_;
  }
  events_ = nullptr;
}
inline const ::dmi::EventsCfg& ListEventsResponse::events() const {
  const ::dmi::EventsCfg* p = events_;
  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.events)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventsCfg*>(
      &::dmi::_EventsCfg_default_instance_);
}
inline ::dmi::EventsCfg* ListEventsResponse::release_events() {
  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.events)
  
  ::dmi::EventsCfg* temp = events_;
  events_ = nullptr;
  return temp;
}
inline ::dmi::EventsCfg* ListEventsResponse::mutable_events() {
  
  if (events_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::EventsCfg>(GetArenaNoVirtual());
    events_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.events)
  return events_;
}
inline void ListEventsResponse::set_allocated_events(::dmi::EventsCfg* events) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete events_;
  }
  if (events) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      events = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, events, submessage_arena);
    }
    
  } else {
    
  }
  events_ = events;
  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.events)
}

// string reason_detail = 4;
inline void ListEventsResponse::clear_reason_detail() {
  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& ListEventsResponse::reason_detail() const {
  // @@protoc_insertion_point(field_get:dmi.ListEventsResponse.reason_detail)
  return reason_detail_.GetNoArena();
}
inline void ListEventsResponse::set_reason_detail(const ::std::string& value) {
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:dmi.ListEventsResponse.reason_detail)
}
#if LANG_CXX11
inline void ListEventsResponse::set_reason_detail(::std::string&& value) {
  
  reason_detail_.SetNoArena(
    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
  // @@protoc_insertion_point(field_set_rvalue:dmi.ListEventsResponse.reason_detail)
}
#endif
inline void ListEventsResponse::set_reason_detail(const char* value) {
  GOOGLE_DCHECK(value != nullptr);
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:dmi.ListEventsResponse.reason_detail)
}
inline void ListEventsResponse::set_reason_detail(const char* value, size_t size) {
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:dmi.ListEventsResponse.reason_detail)
}
inline ::std::string* ListEventsResponse::mutable_reason_detail() {
  
  // @@protoc_insertion_point(field_mutable:dmi.ListEventsResponse.reason_detail)
  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* ListEventsResponse::release_reason_detail() {
  // @@protoc_insertion_point(field_release:dmi.ListEventsResponse.reason_detail)
  
  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void ListEventsResponse::set_allocated_reason_detail(::std::string* reason_detail) {
  if (reason_detail != nullptr) {
    
  } else {
    
  }
  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
  // @@protoc_insertion_point(field_set_allocated:dmi.ListEventsResponse.reason_detail)
}

// -------------------------------------------------------------------

// EventsConfigurationRequest

// .dmi.Uuid device_uuid = 1;
inline bool EventsConfigurationRequest::has_device_uuid() const {
  return this != internal_default_instance() && device_uuid_ != nullptr;
}
inline const ::dmi::Uuid& EventsConfigurationRequest::device_uuid() const {
  const ::dmi::Uuid* p = device_uuid_;
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.device_uuid)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
      &::dmi::_Uuid_default_instance_);
}
inline ::dmi::Uuid* EventsConfigurationRequest::release_device_uuid() {
  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.device_uuid)
  
  ::dmi::Uuid* temp = device_uuid_;
  device_uuid_ = nullptr;
  return temp;
}
inline ::dmi::Uuid* EventsConfigurationRequest::mutable_device_uuid() {
  
  if (device_uuid_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
    device_uuid_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.device_uuid)
  return device_uuid_;
}
inline void EventsConfigurationRequest::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
  }
  if (device_uuid) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, device_uuid, submessage_arena);
    }
    
  } else {
    
  }
  device_uuid_ = device_uuid;
  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationRequest.device_uuid)
}

// .dmi.EventsCfg changes = 2;
inline bool EventsConfigurationRequest::has_changes() const {
  return operation_case() == kChanges;
}
inline void EventsConfigurationRequest::set_has_changes() {
  _oneof_case_[0] = kChanges;
}
inline void EventsConfigurationRequest::clear_changes() {
  if (has_changes()) {
    delete operation_.changes_;
    clear_has_operation();
  }
}
inline ::dmi::EventsCfg* EventsConfigurationRequest::release_changes() {
  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.changes)
  if (has_changes()) {
    clear_has_operation();
      ::dmi::EventsCfg* temp = operation_.changes_;
    operation_.changes_ = nullptr;
    return temp;
  } else {
    return nullptr;
  }
}
inline const ::dmi::EventsCfg& EventsConfigurationRequest::changes() const {
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.changes)
  return has_changes()
      ? *operation_.changes_
      : *reinterpret_cast< ::dmi::EventsCfg*>(&::dmi::_EventsCfg_default_instance_);
}
inline ::dmi::EventsCfg* EventsConfigurationRequest::mutable_changes() {
  if (!has_changes()) {
    clear_operation();
    set_has_changes();
    operation_.changes_ = CreateMaybeMessage< ::dmi::EventsCfg >(
        GetArenaNoVirtual());
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.changes)
  return operation_.changes_;
}

// bool reset_to_default = 3;
inline bool EventsConfigurationRequest::has_reset_to_default() const {
  return operation_case() == kResetToDefault;
}
inline void EventsConfigurationRequest::set_has_reset_to_default() {
  _oneof_case_[0] = kResetToDefault;
}
inline void EventsConfigurationRequest::clear_reset_to_default() {
  if (has_reset_to_default()) {
    operation_.reset_to_default_ = false;
    clear_has_operation();
  }
}
inline bool EventsConfigurationRequest::reset_to_default() const {
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.reset_to_default)
  if (has_reset_to_default()) {
    return operation_.reset_to_default_;
  }
  return false;
}
inline void EventsConfigurationRequest::set_reset_to_default(bool value) {
  if (!has_reset_to_default()) {
    clear_operation();
    set_has_reset_to_default();
  }
  operation_.reset_to_default_ = value;
  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationRequest.reset_to_default)
}

// .dmi.Uuid component_uuid = 4;
inline bool EventsConfigurationRequest::has_component_uuid() const {
  return this != internal_default_instance() && component_uuid_ != nullptr;
}
inline const ::dmi::Uuid& EventsConfigurationRequest::component_uuid() const {
  const ::dmi::Uuid* p = component_uuid_;
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationRequest.component_uuid)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
      &::dmi::_Uuid_default_instance_);
}
inline ::dmi::Uuid* EventsConfigurationRequest::release_component_uuid() {
  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationRequest.component_uuid)
  
  ::dmi::Uuid* temp = component_uuid_;
  component_uuid_ = nullptr;
  return temp;
}
inline ::dmi::Uuid* EventsConfigurationRequest::mutable_component_uuid() {
  
  if (component_uuid_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
    component_uuid_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationRequest.component_uuid)
  return component_uuid_;
}
inline void EventsConfigurationRequest::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
  }
  if (component_uuid) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, component_uuid, submessage_arena);
    }
    
  } else {
    
  }
  component_uuid_ = component_uuid;
  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationRequest.component_uuid)
}

inline bool EventsConfigurationRequest::has_operation() const {
  return operation_case() != OPERATION_NOT_SET;
}
inline void EventsConfigurationRequest::clear_has_operation() {
  _oneof_case_[0] = OPERATION_NOT_SET;
}
inline EventsConfigurationRequest::OperationCase EventsConfigurationRequest::operation_case() const {
  return EventsConfigurationRequest::OperationCase(_oneof_case_[0]);
}
// -------------------------------------------------------------------

// EventsConfigurationResponse

// .dmi.Status status = 1;
inline void EventsConfigurationResponse::clear_status() {
  status_ = 0;
}
inline ::dmi::Status EventsConfigurationResponse::status() const {
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.status)
  return static_cast< ::dmi::Status >(status_);
}
inline void EventsConfigurationResponse::set_status(::dmi::Status value) {
  
  status_ = value;
  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.status)
}

// .dmi.EventsConfigurationResponse.Reason reason = 2;
inline void EventsConfigurationResponse::clear_reason() {
  reason_ = 0;
}
inline ::dmi::EventsConfigurationResponse_Reason EventsConfigurationResponse::reason() const {
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason)
  return static_cast< ::dmi::EventsConfigurationResponse_Reason >(reason_);
}
inline void EventsConfigurationResponse::set_reason(::dmi::EventsConfigurationResponse_Reason value) {
  
  reason_ = value;
  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason)
}

// string reason_detail = 3;
inline void EventsConfigurationResponse::clear_reason_detail() {
  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& EventsConfigurationResponse::reason_detail() const {
  // @@protoc_insertion_point(field_get:dmi.EventsConfigurationResponse.reason_detail)
  return reason_detail_.GetNoArena();
}
inline void EventsConfigurationResponse::set_reason_detail(const ::std::string& value) {
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:dmi.EventsConfigurationResponse.reason_detail)
}
#if LANG_CXX11
inline void EventsConfigurationResponse::set_reason_detail(::std::string&& value) {
  
  reason_detail_.SetNoArena(
    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
  // @@protoc_insertion_point(field_set_rvalue:dmi.EventsConfigurationResponse.reason_detail)
}
#endif
inline void EventsConfigurationResponse::set_reason_detail(const char* value) {
  GOOGLE_DCHECK(value != nullptr);
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:dmi.EventsConfigurationResponse.reason_detail)
}
inline void EventsConfigurationResponse::set_reason_detail(const char* value, size_t size) {
  
  reason_detail_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:dmi.EventsConfigurationResponse.reason_detail)
}
inline ::std::string* EventsConfigurationResponse::mutable_reason_detail() {
  
  // @@protoc_insertion_point(field_mutable:dmi.EventsConfigurationResponse.reason_detail)
  return reason_detail_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* EventsConfigurationResponse::release_reason_detail() {
  // @@protoc_insertion_point(field_release:dmi.EventsConfigurationResponse.reason_detail)
  
  return reason_detail_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void EventsConfigurationResponse::set_allocated_reason_detail(::std::string* reason_detail) {
  if (reason_detail != nullptr) {
    
  } else {
    
  }
  reason_detail_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), reason_detail);
  // @@protoc_insertion_point(field_set_allocated:dmi.EventsConfigurationResponse.reason_detail)
}

// -------------------------------------------------------------------

// EventMetaData

// .dmi.Uuid device_uuid = 1;
inline bool EventMetaData::has_device_uuid() const {
  return this != internal_default_instance() && device_uuid_ != nullptr;
}
inline const ::dmi::Uuid& EventMetaData::device_uuid() const {
  const ::dmi::Uuid* p = device_uuid_;
  // @@protoc_insertion_point(field_get:dmi.EventMetaData.device_uuid)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
      &::dmi::_Uuid_default_instance_);
}
inline ::dmi::Uuid* EventMetaData::release_device_uuid() {
  // @@protoc_insertion_point(field_release:dmi.EventMetaData.device_uuid)
  
  ::dmi::Uuid* temp = device_uuid_;
  device_uuid_ = nullptr;
  return temp;
}
inline ::dmi::Uuid* EventMetaData::mutable_device_uuid() {
  
  if (device_uuid_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
    device_uuid_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.device_uuid)
  return device_uuid_;
}
inline void EventMetaData::set_allocated_device_uuid(::dmi::Uuid* device_uuid) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::google::protobuf::MessageLite*>(device_uuid_);
  }
  if (device_uuid) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      device_uuid = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, device_uuid, submessage_arena);
    }
    
  } else {
    
  }
  device_uuid_ = device_uuid;
  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.device_uuid)
}

// .dmi.Uuid component_uuid = 2;
inline bool EventMetaData::has_component_uuid() const {
  return this != internal_default_instance() && component_uuid_ != nullptr;
}
inline const ::dmi::Uuid& EventMetaData::component_uuid() const {
  const ::dmi::Uuid* p = component_uuid_;
  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_uuid)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::Uuid*>(
      &::dmi::_Uuid_default_instance_);
}
inline ::dmi::Uuid* EventMetaData::release_component_uuid() {
  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_uuid)
  
  ::dmi::Uuid* temp = component_uuid_;
  component_uuid_ = nullptr;
  return temp;
}
inline ::dmi::Uuid* EventMetaData::mutable_component_uuid() {
  
  if (component_uuid_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::Uuid>(GetArenaNoVirtual());
    component_uuid_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_uuid)
  return component_uuid_;
}
inline void EventMetaData::set_allocated_component_uuid(::dmi::Uuid* component_uuid) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::google::protobuf::MessageLite*>(component_uuid_);
  }
  if (component_uuid) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      component_uuid = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, component_uuid, submessage_arena);
    }
    
  } else {
    
  }
  component_uuid_ = component_uuid;
  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_uuid)
}

// string component_name = 3;
inline void EventMetaData::clear_component_name() {
  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& EventMetaData::component_name() const {
  // @@protoc_insertion_point(field_get:dmi.EventMetaData.component_name)
  return component_name_.GetNoArena();
}
inline void EventMetaData::set_component_name(const ::std::string& value) {
  
  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:dmi.EventMetaData.component_name)
}
#if LANG_CXX11
inline void EventMetaData::set_component_name(::std::string&& value) {
  
  component_name_.SetNoArena(
    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
  // @@protoc_insertion_point(field_set_rvalue:dmi.EventMetaData.component_name)
}
#endif
inline void EventMetaData::set_component_name(const char* value) {
  GOOGLE_DCHECK(value != nullptr);
  
  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:dmi.EventMetaData.component_name)
}
inline void EventMetaData::set_component_name(const char* value, size_t size) {
  
  component_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:dmi.EventMetaData.component_name)
}
inline ::std::string* EventMetaData::mutable_component_name() {
  
  // @@protoc_insertion_point(field_mutable:dmi.EventMetaData.component_name)
  return component_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* EventMetaData::release_component_name() {
  // @@protoc_insertion_point(field_release:dmi.EventMetaData.component_name)
  
  return component_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void EventMetaData::set_allocated_component_name(::std::string* component_name) {
  if (component_name != nullptr) {
    
  } else {
    
  }
  component_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), component_name);
  // @@protoc_insertion_point(field_set_allocated:dmi.EventMetaData.component_name)
}

// -------------------------------------------------------------------

// Event

// .dmi.EventMetaData event_metadata = 1;
inline bool Event::has_event_metadata() const {
  return this != internal_default_instance() && event_metadata_ != nullptr;
}
inline void Event::clear_event_metadata() {
  if (GetArenaNoVirtual() == nullptr && event_metadata_ != nullptr) {
    delete event_metadata_;
  }
  event_metadata_ = nullptr;
}
inline const ::dmi::EventMetaData& Event::event_metadata() const {
  const ::dmi::EventMetaData* p = event_metadata_;
  // @@protoc_insertion_point(field_get:dmi.Event.event_metadata)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::EventMetaData*>(
      &::dmi::_EventMetaData_default_instance_);
}
inline ::dmi::EventMetaData* Event::release_event_metadata() {
  // @@protoc_insertion_point(field_release:dmi.Event.event_metadata)
  
  ::dmi::EventMetaData* temp = event_metadata_;
  event_metadata_ = nullptr;
  return temp;
}
inline ::dmi::EventMetaData* Event::mutable_event_metadata() {
  
  if (event_metadata_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::EventMetaData>(GetArenaNoVirtual());
    event_metadata_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.Event.event_metadata)
  return event_metadata_;
}
inline void Event::set_allocated_event_metadata(::dmi::EventMetaData* event_metadata) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete event_metadata_;
  }
  if (event_metadata) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      event_metadata = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, event_metadata, submessage_arena);
    }
    
  } else {
    
  }
  event_metadata_ = event_metadata;
  // @@protoc_insertion_point(field_set_allocated:dmi.Event.event_metadata)
}

// .dmi.EventIds event_id = 2;
inline void Event::clear_event_id() {
  event_id_ = 0;
}
inline ::dmi::EventIds Event::event_id() const {
  // @@protoc_insertion_point(field_get:dmi.Event.event_id)
  return static_cast< ::dmi::EventIds >(event_id_);
}
inline void Event::set_event_id(::dmi::EventIds value) {
  
  event_id_ = value;
  // @@protoc_insertion_point(field_set:dmi.Event.event_id)
}

// .google.protobuf.Timestamp raised_ts = 3;
inline bool Event::has_raised_ts() const {
  return this != internal_default_instance() && raised_ts_ != nullptr;
}
inline const ::google::protobuf::Timestamp& Event::raised_ts() const {
  const ::google::protobuf::Timestamp* p = raised_ts_;
  // @@protoc_insertion_point(field_get:dmi.Event.raised_ts)
  return p != nullptr ? *p : *reinterpret_cast<const ::google::protobuf::Timestamp*>(
      &::google::protobuf::_Timestamp_default_instance_);
}
inline ::google::protobuf::Timestamp* Event::release_raised_ts() {
  // @@protoc_insertion_point(field_release:dmi.Event.raised_ts)
  
  ::google::protobuf::Timestamp* temp = raised_ts_;
  raised_ts_ = nullptr;
  return temp;
}
inline ::google::protobuf::Timestamp* Event::mutable_raised_ts() {
  
  if (raised_ts_ == nullptr) {
    auto* p = CreateMaybeMessage<::google::protobuf::Timestamp>(GetArenaNoVirtual());
    raised_ts_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.Event.raised_ts)
  return raised_ts_;
}
inline void Event::set_allocated_raised_ts(::google::protobuf::Timestamp* raised_ts) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete reinterpret_cast< ::google::protobuf::MessageLite*>(raised_ts_);
  }
  if (raised_ts) {
    ::google::protobuf::Arena* submessage_arena =
      reinterpret_cast<::google::protobuf::MessageLite*>(raised_ts)->GetArena();
    if (message_arena != submessage_arena) {
      raised_ts = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, raised_ts, submessage_arena);
    }
    
  } else {
    
  }
  raised_ts_ = raised_ts;
  // @@protoc_insertion_point(field_set_allocated:dmi.Event.raised_ts)
}

// .dmi.ThresholdInformation threshold_info = 4;
inline bool Event::has_threshold_info() const {
  return this != internal_default_instance() && threshold_info_ != nullptr;
}
inline void Event::clear_threshold_info() {
  if (GetArenaNoVirtual() == nullptr && threshold_info_ != nullptr) {
    delete threshold_info_;
  }
  threshold_info_ = nullptr;
}
inline const ::dmi::ThresholdInformation& Event::threshold_info() const {
  const ::dmi::ThresholdInformation* p = threshold_info_;
  // @@protoc_insertion_point(field_get:dmi.Event.threshold_info)
  return p != nullptr ? *p : *reinterpret_cast<const ::dmi::ThresholdInformation*>(
      &::dmi::_ThresholdInformation_default_instance_);
}
inline ::dmi::ThresholdInformation* Event::release_threshold_info() {
  // @@protoc_insertion_point(field_release:dmi.Event.threshold_info)
  
  ::dmi::ThresholdInformation* temp = threshold_info_;
  threshold_info_ = nullptr;
  return temp;
}
inline ::dmi::ThresholdInformation* Event::mutable_threshold_info() {
  
  if (threshold_info_ == nullptr) {
    auto* p = CreateMaybeMessage<::dmi::ThresholdInformation>(GetArenaNoVirtual());
    threshold_info_ = p;
  }
  // @@protoc_insertion_point(field_mutable:dmi.Event.threshold_info)
  return threshold_info_;
}
inline void Event::set_allocated_threshold_info(::dmi::ThresholdInformation* threshold_info) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == nullptr) {
    delete threshold_info_;
  }
  if (threshold_info) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      threshold_info = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, threshold_info, submessage_arena);
    }
    
  } else {
    
  }
  threshold_info_ = threshold_info;
  // @@protoc_insertion_point(field_set_allocated:dmi.Event.threshold_info)
}

// string add_info = 5;
inline void Event::clear_add_info() {
  add_info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline const ::std::string& Event::add_info() const {
  // @@protoc_insertion_point(field_get:dmi.Event.add_info)
  return add_info_.GetNoArena();
}
inline void Event::set_add_info(const ::std::string& value) {
  
  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value);
  // @@protoc_insertion_point(field_set:dmi.Event.add_info)
}
#if LANG_CXX11
inline void Event::set_add_info(::std::string&& value) {
  
  add_info_.SetNoArena(
    &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value));
  // @@protoc_insertion_point(field_set_rvalue:dmi.Event.add_info)
}
#endif
inline void Event::set_add_info(const char* value) {
  GOOGLE_DCHECK(value != nullptr);
  
  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value));
  // @@protoc_insertion_point(field_set_char:dmi.Event.add_info)
}
inline void Event::set_add_info(const char* value, size_t size) {
  
  add_info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),
      ::std::string(reinterpret_cast<const char*>(value), size));
  // @@protoc_insertion_point(field_set_pointer:dmi.Event.add_info)
}
inline ::std::string* Event::mutable_add_info() {
  
  // @@protoc_insertion_point(field_mutable:dmi.Event.add_info)
  return add_info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline ::std::string* Event::release_add_info() {
  // @@protoc_insertion_point(field_release:dmi.Event.add_info)
  
  return add_info_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}
inline void Event::set_allocated_add_info(::std::string* add_info) {
  if (add_info != nullptr) {
    
  } else {
    
  }
  add_info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), add_info);
  // @@protoc_insertion_point(field_set_allocated:dmi.Event.add_info)
}

#ifdef __GNUC__
  #pragma GCC diagnostic pop
#endif  // __GNUC__
// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------

// -------------------------------------------------------------------


// @@protoc_insertion_point(namespace_scope)

}  // namespace dmi

namespace google {
namespace protobuf {

template <> struct is_proto_enum< ::dmi::ListEventsResponse_Reason> : ::std::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::dmi::ListEventsResponse_Reason>() {
  return ::dmi::ListEventsResponse_Reason_descriptor();
}
template <> struct is_proto_enum< ::dmi::EventsConfigurationResponse_Reason> : ::std::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventsConfigurationResponse_Reason>() {
  return ::dmi::EventsConfigurationResponse_Reason_descriptor();
}
template <> struct is_proto_enum< ::dmi::EventIds> : ::std::true_type {};
template <>
inline const EnumDescriptor* GetEnumDescriptor< ::dmi::EventIds>() {
  return ::dmi::EventIds_descriptor();
}

}  // namespace protobuf
}  // namespace google

// @@protoc_insertion_point(global_scope)

#include <google/protobuf/port_undef.inc>
#endif  // PROTOBUF_INCLUDED_dmi_2fhw_5fevents_5fmgmt_5fservice_2eproto
