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

#include "dmi/hw_metrics_mgmt_service.pb.h"

#include <algorithm>

#include <google/protobuf/stubs/common.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/extension_set.h>
#include <google/protobuf/wire_format_lite_inl.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/generated_message_reflection.h>
#include <google/protobuf/reflection_ops.h>
#include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes)
#include <google/protobuf/port_def.inc>

extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Uuid_dmi_2fhw_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_ComponentSensorData_dmi_2fhw_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto ::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto;
namespace dmi {
class MetricConfigDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<MetricConfig> _instance;
} _MetricConfig_default_instance_;
class MetricsConfigDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfig> _instance;
} _MetricsConfig_default_instance_;
class ListMetricsResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<ListMetricsResponse> _instance;
} _ListMetricsResponse_default_instance_;
class MetricsConfigurationRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationRequest> _instance;
  const ::dmi::MetricsConfig* changes_;
  bool reset_to_default_;
} _MetricsConfigurationRequest_default_instance_;
class MetricsConfigurationResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<MetricsConfigurationResponse> _instance;
} _MetricsConfigurationResponse_default_instance_;
class MetricMetaDataDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<MetricMetaData> _instance;
} _MetricMetaData_default_instance_;
class MetricDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<Metric> _instance;
} _Metric_default_instance_;
class GetMetricRequestDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricRequest> _instance;
} _GetMetricRequest_default_instance_;
class GetMetricResponseDefaultTypeInternal {
 public:
  ::google::protobuf::internal::ExplicitlyConstructed<GetMetricResponse> _instance;
} _GetMetricResponse_default_instance_;
}  // namespace dmi
static void InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_MetricConfig_default_instance_;
    new (ptr) ::dmi::MetricConfig();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::MetricConfig::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<0> scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};

static void InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_MetricsConfig_default_instance_;
    new (ptr) ::dmi::MetricsConfig();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::MetricsConfig::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};

static void InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_ListMetricsResponse_default_instance_;
    new (ptr) ::dmi::ListMetricsResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::ListMetricsResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};

static void InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_MetricsConfigurationRequest_default_instance_;
    new (ptr) ::dmi::MetricsConfigurationRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::MetricsConfigurationRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<2> scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,
      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};

static void InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_MetricsConfigurationResponse_default_instance_;
    new (ptr) ::dmi::MetricsConfigurationResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::MetricsConfigurationResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<0> scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsMetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {}};

static void InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_MetricMetaData_default_instance_;
    new (ptr) ::dmi::MetricMetaData();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::MetricMetaData::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsMetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_Uuid_dmi_2fhw_2eproto.base,}};

static void InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_Metric_default_instance_;
    new (ptr) ::dmi::Metric();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::Metric::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<2> scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsMetric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,
      &scc_info_ComponentSensorData_dmi_2fhw_2eproto.base,}};

static void InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_GetMetricRequest_default_instance_;
    new (ptr) ::dmi::GetMetricRequest();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::GetMetricRequest::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};

static void InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  GOOGLE_PROTOBUF_VERIFY_VERSION;

  {
    void* ptr = &::dmi::_GetMetricResponse_default_instance_;
    new (ptr) ::dmi::GetMetricResponse();
    ::google::protobuf::internal::OnShutdownDestroyMessage(ptr);
  }
  ::dmi::GetMetricResponse::InitAsDefaultInstance();
}

::google::protobuf::internal::SCCInfo<1> scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto =
    {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 1, InitDefaultsGetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto}, {
      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base,}};

void InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  ::google::protobuf::internal::InitSCC(&scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::google::protobuf::internal::InitSCC(&scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
}

::google::protobuf::Metadata file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[9];
const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[4];
constexpr ::google::protobuf::ServiceDescriptor const** file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = nullptr;

const ::google::protobuf::uint32 TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, metric_id_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, is_configured_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricConfig, poll_interval_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfig, metrics_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, metrics_),
  PROTOBUF_FIELD_OFFSET(::dmi::ListMetricsResponse, reason_detail_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, _oneof_case_[0]),
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, device_uuid_),
  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, changes_),
  offsetof(::dmi::MetricsConfigurationRequestDefaultTypeInternal, reset_to_default_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationRequest, operation_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricsConfigurationResponse, reason_detail_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, device_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_uuid_),
  PROTOBUF_FIELD_OFFSET(::dmi::MetricMetaData, component_name_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::Metric, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_id_),
  PROTOBUF_FIELD_OFFSET(::dmi::Metric, metric_metadata_),
  PROTOBUF_FIELD_OFFSET(::dmi::Metric, value_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, meta_data_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricRequest, metric_id_),
  ~0u,  // no _has_bits_
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, _internal_metadata_),
  ~0u,  // no _extensions_
  ~0u,  // no _oneof_case_
  ~0u,  // no _weak_field_map_
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, status_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, metric_),
  PROTOBUF_FIELD_OFFSET(::dmi::GetMetricResponse, reason_detail_),
};
static const ::google::protobuf::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
  { 0, -1, sizeof(::dmi::MetricConfig)},
  { 8, -1, sizeof(::dmi::MetricsConfig)},
  { 14, -1, sizeof(::dmi::ListMetricsResponse)},
  { 23, -1, sizeof(::dmi::MetricsConfigurationRequest)},
  { 32, -1, sizeof(::dmi::MetricsConfigurationResponse)},
  { 40, -1, sizeof(::dmi::MetricMetaData)},
  { 48, -1, sizeof(::dmi::Metric)},
  { 56, -1, sizeof(::dmi::GetMetricRequest)},
  { 63, -1, sizeof(::dmi::GetMetricResponse)},
};

static ::google::protobuf::Message const * const file_default_instances[] = {
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricConfig_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfig_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_ListMetricsResponse_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricsConfigurationResponse_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_MetricMetaData_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_Metric_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricRequest_default_instance_),
  reinterpret_cast<const ::google::protobuf::Message*>(&::dmi::_GetMetricResponse_default_instance_),
};

::google::protobuf::internal::AssignDescriptorsTable assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
  {}, AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, "dmi/hw_metrics_mgmt_service.proto", schemas,
  file_default_instances, TableStruct_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto::offsets,
  file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 9, file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, file_level_service_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
};

const char descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[] =
  "\n!dmi/hw_metrics_mgmt_service.proto\022\003dmi"
  "\032\021dmi/commons.proto\032\014dmi/hw.proto\032\033googl"
  "e/protobuf/empty.proto\"a\n\014MetricConfig\022#"
  "\n\tmetric_id\030\001 \001(\0162\020.dmi.MetricNames\022\025\n\ri"
  "s_configured\030\002 \001(\010\022\025\n\rpoll_interval\030\003 \001("
  "\r\"3\n\rMetricsConfig\022\"\n\007metrics\030\001 \003(\0132\021.dm"
  "i.MetricConfig\"\377\001\n\023ListMetricsResponse\022\033"
  "\n\006status\030\001 \001(\0162\013.dmi.Status\022/\n\006reason\030\002 "
  "\001(\0162\037.dmi.ListMetricsResponse.Reason\022#\n\007"
  "metrics\030\003 \001(\0132\022.dmi.MetricsConfig\022\025\n\rrea"
  "son_detail\030\004 \001(\t\"^\n\006Reason\022\024\n\020UNDEFINED_"
  "REASON\020\000\022\022\n\016UNKNOWN_DEVICE\020\001\022\022\n\016INTERNAL"
  "_ERROR\020\002\022\026\n\022DEVICE_UNREACHABLE\020\003\"\215\001\n\033Met"
  "ricsConfigurationRequest\022\036\n\013device_uuid\030"
  "\001 \001(\0132\t.dmi.Uuid\022%\n\007changes\030\002 \001(\0132\022.dmi."
  "MetricsConfigH\000\022\032\n\020reset_to_default\030\003 \001("
  "\010H\000B\013\n\toperation\"\240\002\n\034MetricsConfiguratio"
  "nResponse\022\033\n\006status\030\001 \001(\0162\013.dmi.Status\0228"
  "\n\006reason\030\002 \001(\0162(.dmi.MetricsConfiguratio"
  "nResponse.Reason\022\025\n\rreason_detail\030\003 \001(\t\""
  "\221\001\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKN"
  "OWN_DEVICE\020\001\022\022\n\016INTERNAL_ERROR\020\002\022\035\n\031POLL"
  "_INTERVAL_UNSUPPORTED\020\003\022\022\n\016INVALID_METRI"
  "C\020\004\022\026\n\022DEVICE_UNREACHABLE\020\005\"k\n\016MetricMet"
  "aData\022\036\n\013device_uuid\030\001 \001(\0132\t.dmi.Uuid\022!\n"
  "\016component_uuid\030\002 \001(\0132\t.dmi.Uuid\022\026\n\016comp"
  "onent_name\030\003 \001(\t\"\204\001\n\006Metric\022#\n\tmetric_id"
  "\030\001 \001(\0162\020.dmi.MetricNames\022,\n\017metric_metad"
  "ata\030\002 \001(\0132\023.dmi.MetricMetaData\022\'\n\005value\030"
  "\003 \001(\0132\030.dmi.ComponentSensorData\"_\n\020GetMe"
  "tricRequest\022&\n\tmeta_data\030\001 \001(\0132\023.dmi.Met"
  "ricMetaData\022#\n\tmetric_id\030\002 \001(\0162\020.dmi.Met"
  "ricNames\"\237\002\n\021GetMetricResponse\022\033\n\006status"
  "\030\001 \001(\0162\013.dmi.Status\022-\n\006reason\030\002 \001(\0162\035.dm"
  "i.GetMetricResponse.Reason\022\033\n\006metric\030\003 \001"
  "(\0132\013.dmi.Metric\022\025\n\rreason_detail\030\004 \001(\t\"\211"
  "\001\n\006Reason\022\024\n\020UNDEFINED_REASON\020\000\022\022\n\016UNKNO"
  "WN_DEVICE\020\001\022\025\n\021UNKNOWN_COMPONENT\020\002\022\022\n\016IN"
  "TERNAL_ERROR\020\003\022\022\n\016INVALID_METRIC\020\004\022\026\n\022DE"
  "VICE_UNREACHABLE\020\005*\331\005\n\013MetricNames\022\031\n\025ME"
  "TRIC_NAME_UNDEFINED\020\000\022\024\n\020METRIC_FAN_SPEE"
  "D\020\001\022\023\n\017METRIC_CPU_TEMP\020d\022\037\n\033METRIC_CPU_U"
  "SAGE_PERCENTAGE\020e\022\034\n\027METRIC_TRANSCEIVER_"
  "TEMP\020\310\001\022\037\n\032METRIC_TRANSCEIVER_VOLTAGE\020\311\001"
  "\022\034\n\027METRIC_TRANSCEIVER_BIAS\020\312\001\022 \n\033METRIC"
  "_TRANSCEIVER_RX_POWER\020\313\001\022 \n\033METRIC_TRANS"
  "CEIVER_TX_POWER\020\314\001\022\"\n\035METRIC_TRANSCEIVER"
  "_WAVELENGTH\020\315\001\022\025\n\020METRIC_DISK_TEMP\020\254\002\022\031\n"
  "\024METRIC_DISK_CAPACITY\020\255\002\022\026\n\021METRIC_DISK_"
  "USAGE\020\256\002\022!\n\034METRIC_DISK_USAGE_PERCENTAGE"
  "\020\257\002\022&\n!METRIC_DISK_READ_WRITE_PERCENTAGE"
  "\020\260\002\022(\n#METRIC_DISK_FAULTY_CELLS_PERCENTA"
  "GE\020\261\002\022\024\n\017METRIC_RAM_TEMP\020\220\003\022\030\n\023METRIC_RA"
  "M_CAPACITY\020\221\003\022\025\n\020METRIC_RAM_USAGE\020\222\003\022 \n\033"
  "METRIC_RAM_USAGE_PERCENTAGE\020\223\003\022\025\n\020METRIC"
  "_POWER_MAX\020\364\003\022\027\n\022METRIC_POWER_USAGE\020\365\003\022\""
  "\n\035METRIC_POWER_USAGE_PERCENTAGE\020\366\003\022\"\n\035ME"
  "TRIC_INNER_SURROUNDING_TEMP\020\330\0042\261\002\n\036Nativ"
  "eMetricsManagementService\0228\n\013ListMetrics"
  "\022\017.dmi.HardwareID\032\030.dmi.ListMetricsRespo"
  "nse\022a\n\032UpdateMetricsConfiguration\022 .dmi."
  "MetricsConfigurationRequest\032!.dmi.Metric"
  "sConfigurationResponse\022:\n\tGetMetric\022\025.dm"
  "i.GetMetricRequest\032\026.dmi.GetMetricRespon"
  "se\0226\n\rStreamMetrics\022\026.google.protobuf.Em"
  "pty\032\013.dmi.Metric0\001B;Z9github.com/opencor"
  "d/device-management-interface/v3/go/dmib"
  "\006proto3"
  ;
::google::protobuf::internal::DescriptorTable descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = {
  false, InitDefaults_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 
  descriptor_table_protodef_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto,
  "dmi/hw_metrics_mgmt_service.proto", &assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, 2687,
};

void AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto() {
  static constexpr ::google::protobuf::internal::InitFunc deps[3] =
  {
    ::AddDescriptors_dmi_2fcommons_2eproto,
    ::AddDescriptors_dmi_2fhw_2eproto,
    ::AddDescriptors_google_2fprotobuf_2fempty_2eproto,
  };
 ::google::protobuf::internal::AddDescriptors(&descriptor_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto, deps, 3);
}

// Force running AddDescriptors() at dynamic initialization time.
static bool dynamic_init_dummy_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto = []() { AddDescriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto(); return true; }();
namespace dmi {
const ::google::protobuf::EnumDescriptor* ListMetricsResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[0];
}
bool ListMetricsResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const ListMetricsResponse_Reason ListMetricsResponse::UNDEFINED_REASON;
const ListMetricsResponse_Reason ListMetricsResponse::UNKNOWN_DEVICE;
const ListMetricsResponse_Reason ListMetricsResponse::INTERNAL_ERROR;
const ListMetricsResponse_Reason ListMetricsResponse::DEVICE_UNREACHABLE;
const ListMetricsResponse_Reason ListMetricsResponse::Reason_MIN;
const ListMetricsResponse_Reason ListMetricsResponse::Reason_MAX;
const int ListMetricsResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* MetricsConfigurationResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[1];
}
bool MetricsConfigurationResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNDEFINED_REASON;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::UNKNOWN_DEVICE;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INTERNAL_ERROR;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::POLL_INTERVAL_UNSUPPORTED;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::INVALID_METRIC;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::DEVICE_UNREACHABLE;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MIN;
const MetricsConfigurationResponse_Reason MetricsConfigurationResponse::Reason_MAX;
const int MetricsConfigurationResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* GetMetricResponse_Reason_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[2];
}
bool GetMetricResponse_Reason_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      return true;
    default:
      return false;
  }
}

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const GetMetricResponse_Reason GetMetricResponse::UNDEFINED_REASON;
const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_DEVICE;
const GetMetricResponse_Reason GetMetricResponse::UNKNOWN_COMPONENT;
const GetMetricResponse_Reason GetMetricResponse::INTERNAL_ERROR;
const GetMetricResponse_Reason GetMetricResponse::INVALID_METRIC;
const GetMetricResponse_Reason GetMetricResponse::DEVICE_UNREACHABLE;
const GetMetricResponse_Reason GetMetricResponse::Reason_MIN;
const GetMetricResponse_Reason GetMetricResponse::Reason_MAX;
const int GetMetricResponse::Reason_ARRAYSIZE;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900
const ::google::protobuf::EnumDescriptor* MetricNames_descriptor() {
  ::google::protobuf::internal::AssignDescriptors(&assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return file_level_enum_descriptors_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[3];
}
bool MetricNames_IsValid(int value) {
  switch (value) {
    case 0:
    case 1:
    case 100:
    case 101:
    case 200:
    case 201:
    case 202:
    case 203:
    case 204:
    case 205:
    case 300:
    case 301:
    case 302:
    case 303:
    case 304:
    case 305:
    case 400:
    case 401:
    case 402:
    case 403:
    case 500:
    case 501:
    case 502:
    case 600:
      return true;
    default:
      return false;
  }
}


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

void MetricConfig::InitAsDefaultInstance() {
}
class MetricConfig::HasBitSetters {
 public:
};

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int MetricConfig::kMetricIdFieldNumber;
const int MetricConfig::kIsConfiguredFieldNumber;
const int MetricConfig::kPollIntervalFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

MetricConfig::MetricConfig()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.MetricConfig)
}
MetricConfig::MetricConfig(const MetricConfig& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::memcpy(&metric_id_, &from.metric_id_,
    static_cast<size_t>(reinterpret_cast<char*>(&poll_interval_) -
    reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
  // @@protoc_insertion_point(copy_constructor:dmi.MetricConfig)
}

void MetricConfig::SharedCtor() {
  ::memset(&metric_id_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&poll_interval_) -
      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
}

MetricConfig::~MetricConfig() {
  // @@protoc_insertion_point(destructor:dmi.MetricConfig)
  SharedDtor();
}

void MetricConfig::SharedDtor() {
}

void MetricConfig::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const MetricConfig& MetricConfig::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_MetricConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void MetricConfig::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.MetricConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  ::memset(&metric_id_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&poll_interval_) -
      reinterpret_cast<char*>(&metric_id_)) + sizeof(poll_interval_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* MetricConfig::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<MetricConfig*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.MetricNames metric_id = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // bool is_configured = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        msg->set_is_configured(::google::protobuf::internal::ReadVarint(&ptr));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // uint32 poll_interval = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
        msg->set_poll_interval(::google::protobuf::internal::ReadVarint(&ptr));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool MetricConfig::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.MetricConfig)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.MetricNames metric_id = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_metric_id(static_cast< ::dmi::MetricNames >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // bool is_configured = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {

          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &is_configured_)));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // uint32 poll_interval = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {

          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   ::google::protobuf::uint32, ::google::protobuf::internal::WireFormatLite::TYPE_UINT32>(
                 input, &poll_interval_)));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.MetricConfig)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.MetricConfig)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void MetricConfig::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.MetricConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->metric_id(), output);
  }

  // bool is_configured = 2;
  if (this->is_configured() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->is_configured(), output);
  }

  // uint32 poll_interval = 3;
  if (this->poll_interval() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteUInt32(3, this->poll_interval(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.MetricConfig)
}

::google::protobuf::uint8* MetricConfig::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->metric_id(), target);
  }

  // bool is_configured = 2;
  if (this->is_configured() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->is_configured(), target);
  }

  // uint32 poll_interval = 3;
  if (this->poll_interval() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(3, this->poll_interval(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricConfig)
  return target;
}

size_t MetricConfig::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.MetricConfig)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
  }

  // bool is_configured = 2;
  if (this->is_configured() != 0) {
    total_size += 1 + 1;
  }

  // uint32 poll_interval = 3;
  if (this->poll_interval() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::UInt32Size(
        this->poll_interval());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void MetricConfig::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricConfig)
  GOOGLE_DCHECK_NE(&from, this);
  const MetricConfig* source =
      ::google::protobuf::DynamicCastToGenerated<MetricConfig>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricConfig)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricConfig)
    MergeFrom(*source);
  }
}

void MetricConfig::MergeFrom(const MetricConfig& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricConfig)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.metric_id() != 0) {
    set_metric_id(from.metric_id());
  }
  if (from.is_configured() != 0) {
    set_is_configured(from.is_configured());
  }
  if (from.poll_interval() != 0) {
    set_poll_interval(from.poll_interval());
  }
}

void MetricConfig::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricConfig)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void MetricConfig::CopyFrom(const MetricConfig& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricConfig)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool MetricConfig::IsInitialized() const {
  return true;
}

void MetricConfig::Swap(MetricConfig* other) {
  if (other == this) return;
  InternalSwap(other);
}
void MetricConfig::InternalSwap(MetricConfig* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(metric_id_, other->metric_id_);
  swap(is_configured_, other->is_configured_);
  swap(poll_interval_, other->poll_interval_);
}

::google::protobuf::Metadata MetricConfig::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void MetricsConfig::InitAsDefaultInstance() {
}
class MetricsConfig::HasBitSetters {
 public:
};

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int MetricsConfig::kMetricsFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

MetricsConfig::MetricsConfig()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.MetricsConfig)
}
MetricsConfig::MetricsConfig(const MetricsConfig& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr),
      metrics_(from.metrics_) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfig)
}

void MetricsConfig::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
}

MetricsConfig::~MetricsConfig() {
  // @@protoc_insertion_point(destructor:dmi.MetricsConfig)
  SharedDtor();
}

void MetricsConfig::SharedDtor() {
}

void MetricsConfig::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const MetricsConfig& MetricsConfig::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfig_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void MetricsConfig::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  metrics_.Clear();
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* MetricsConfig::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<MetricsConfig*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // repeated .dmi.MetricConfig metrics = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        do {
          ptr = ::google::protobuf::io::ReadSize(ptr, &size);
          GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
          parser_till_end = ::dmi::MetricConfig::_InternalParse;
          object = msg->add_metrics();
          if (size > end - ptr) goto len_delim_till_end;
          ptr += size;
          GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
              {parser_till_end, object}, ptr - size, ptr));
          if (ptr >= end) break;
        } while ((::google::protobuf::io::UnalignedLoad<::google::protobuf::uint64>(ptr) & 255) == 10 && (ptr += 1));
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool MetricsConfig::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.MetricsConfig)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // repeated .dmi.MetricConfig metrics = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
                input, add_metrics()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.MetricsConfig)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfig)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void MetricsConfig::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // repeated .dmi.MetricConfig metrics = 1;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1,
      this->metrics(static_cast<int>(i)),
      output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfig)
}

::google::protobuf::uint8* MetricsConfig::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfig)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // repeated .dmi.MetricConfig metrics = 1;
  for (unsigned int i = 0,
      n = static_cast<unsigned int>(this->metrics_size()); i < n; i++) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, this->metrics(static_cast<int>(i)), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfig)
  return target;
}

size_t MetricsConfig::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfig)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // repeated .dmi.MetricConfig metrics = 1;
  {
    unsigned int count = static_cast<unsigned int>(this->metrics_size());
    total_size += 1UL * count;
    for (unsigned int i = 0; i < count; i++) {
      total_size +=
        ::google::protobuf::internal::WireFormatLite::MessageSize(
          this->metrics(static_cast<int>(i)));
    }
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void MetricsConfig::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfig)
  GOOGLE_DCHECK_NE(&from, this);
  const MetricsConfig* source =
      ::google::protobuf::DynamicCastToGenerated<MetricsConfig>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfig)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfig)
    MergeFrom(*source);
  }
}

void MetricsConfig::MergeFrom(const MetricsConfig& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfig)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  metrics_.MergeFrom(from.metrics_);
}

void MetricsConfig::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfig)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void MetricsConfig::CopyFrom(const MetricsConfig& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfig)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool MetricsConfig::IsInitialized() const {
  return true;
}

void MetricsConfig::Swap(MetricsConfig* other) {
  if (other == this) return;
  InternalSwap(other);
}
void MetricsConfig::InternalSwap(MetricsConfig* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  CastToBase(&metrics_)->InternalSwap(CastToBase(&other->metrics_));
}

::google::protobuf::Metadata MetricsConfig::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void ListMetricsResponse::InitAsDefaultInstance() {
  ::dmi::_ListMetricsResponse_default_instance_._instance.get_mutable()->metrics_ = const_cast< ::dmi::MetricsConfig*>(
      ::dmi::MetricsConfig::internal_default_instance());
}
class ListMetricsResponse::HasBitSetters {
 public:
  static const ::dmi::MetricsConfig& metrics(const ListMetricsResponse* msg);
};

const ::dmi::MetricsConfig&
ListMetricsResponse::HasBitSetters::metrics(const ListMetricsResponse* msg) {
  return *msg->metrics_;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int ListMetricsResponse::kStatusFieldNumber;
const int ListMetricsResponse::kReasonFieldNumber;
const int ListMetricsResponse::kMetricsFieldNumber;
const int ListMetricsResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

ListMetricsResponse::ListMetricsResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.ListMetricsResponse)
}
ListMetricsResponse::ListMetricsResponse(const ListMetricsResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_metrics()) {
    metrics_ = new ::dmi::MetricsConfig(*from.metrics_);
  } else {
    metrics_ = nullptr;
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.ListMetricsResponse)
}

void ListMetricsResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&metrics_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&metrics_)) + sizeof(reason_));
}

ListMetricsResponse::~ListMetricsResponse() {
  // @@protoc_insertion_point(destructor:dmi.ListMetricsResponse)
  SharedDtor();
}

void ListMetricsResponse::SharedDtor() {
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete metrics_;
}

void ListMetricsResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const ListMetricsResponse& ListMetricsResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_ListMetricsResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void ListMetricsResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.ListMetricsResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && metrics_ != nullptr) {
    delete metrics_;
  }
  metrics_ = nullptr;
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* ListMetricsResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<ListMetricsResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.ListMetricsResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::ListMetricsResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.MetricsConfig metrics = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
        object = msg->mutable_metrics();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string reason_detail = 4;
      case 4: {
        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.ListMetricsResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool ListMetricsResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.ListMetricsResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.ListMetricsResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::ListMetricsResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.MetricsConfig metrics = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_metrics()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 4;
      case 4: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.ListMetricsResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.ListMetricsResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.ListMetricsResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void ListMetricsResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.ListMetricsResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.ListMetricsResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // .dmi.MetricsConfig metrics = 3;
  if (this->has_metrics()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, HasBitSetters::metrics(this), output);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ListMetricsResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.ListMetricsResponse)
}

::google::protobuf::uint8* ListMetricsResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.ListMetricsResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.ListMetricsResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // .dmi.MetricsConfig metrics = 3;
  if (this->has_metrics()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        3, HasBitSetters::metrics(this), target);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.ListMetricsResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        4, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.ListMetricsResponse)
  return target;
}

size_t ListMetricsResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.ListMetricsResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.MetricsConfig metrics = 3;
  if (this->has_metrics()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *metrics_);
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.ListMetricsResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void ListMetricsResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.ListMetricsResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const ListMetricsResponse* source =
      ::google::protobuf::DynamicCastToGenerated<ListMetricsResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.ListMetricsResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.ListMetricsResponse)
    MergeFrom(*source);
  }
}

void ListMetricsResponse::MergeFrom(const ListMetricsResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.ListMetricsResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_metrics()) {
    mutable_metrics()->::dmi::MetricsConfig::MergeFrom(from.metrics());
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void ListMetricsResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.ListMetricsResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void ListMetricsResponse::CopyFrom(const ListMetricsResponse& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.ListMetricsResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool ListMetricsResponse::IsInitialized() const {
  return true;
}

void ListMetricsResponse::Swap(ListMetricsResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void ListMetricsResponse::InternalSwap(ListMetricsResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(metrics_, other->metrics_);
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata ListMetricsResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void MetricsConfigurationRequest::InitAsDefaultInstance() {
  ::dmi::_MetricsConfigurationRequest_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
  ::dmi::_MetricsConfigurationRequest_default_instance_.changes_ = const_cast< ::dmi::MetricsConfig*>(
      ::dmi::MetricsConfig::internal_default_instance());
  ::dmi::_MetricsConfigurationRequest_default_instance_.reset_to_default_ = false;
}
class MetricsConfigurationRequest::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const MetricsConfigurationRequest* msg);
  static const ::dmi::MetricsConfig& changes(const MetricsConfigurationRequest* msg);
};

const ::dmi::Uuid&
MetricsConfigurationRequest::HasBitSetters::device_uuid(const MetricsConfigurationRequest* msg) {
  return *msg->device_uuid_;
}
const ::dmi::MetricsConfig&
MetricsConfigurationRequest::HasBitSetters::changes(const MetricsConfigurationRequest* msg) {
  return *msg->operation_.changes_;
}
void MetricsConfigurationRequest::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
void MetricsConfigurationRequest::set_allocated_changes(::dmi::MetricsConfig* changes) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  clear_operation();
  if (changes) {
    ::google::protobuf::Arena* submessage_arena = nullptr;
    if (message_arena != submessage_arena) {
      changes = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, changes, submessage_arena);
    }
    set_has_changes();
    operation_.changes_ = changes;
  }
  // @@protoc_insertion_point(field_set_allocated:dmi.MetricsConfigurationRequest.changes)
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int MetricsConfigurationRequest::kDeviceUuidFieldNumber;
const int MetricsConfigurationRequest::kChangesFieldNumber;
const int MetricsConfigurationRequest::kResetToDefaultFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

MetricsConfigurationRequest::MetricsConfigurationRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationRequest)
}
MetricsConfigurationRequest::MetricsConfigurationRequest(const MetricsConfigurationRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  clear_has_operation();
  switch (from.operation_case()) {
    case kChanges: {
      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
      break;
    }
    case kResetToDefault: {
      set_reset_to_default(from.reset_to_default());
      break;
    }
    case OPERATION_NOT_SET: {
      break;
    }
  }
  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationRequest)
}

void MetricsConfigurationRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  device_uuid_ = nullptr;
  clear_has_operation();
}

MetricsConfigurationRequest::~MetricsConfigurationRequest() {
  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationRequest)
  SharedDtor();
}

void MetricsConfigurationRequest::SharedDtor() {
  if (this != internal_default_instance()) delete device_uuid_;
  if (has_operation()) {
    clear_operation();
  }
}

void MetricsConfigurationRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const MetricsConfigurationRequest& MetricsConfigurationRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void MetricsConfigurationRequest::clear_operation() {
// @@protoc_insertion_point(one_of_clear_start:dmi.MetricsConfigurationRequest)
  switch (operation_case()) {
    case kChanges: {
      delete operation_.changes_;
      break;
    }
    case kResetToDefault: {
      // No need to clear
      break;
    }
    case OPERATION_NOT_SET: {
      break;
    }
  }
  _oneof_case_[0] = OPERATION_NOT_SET;
}


void MetricsConfigurationRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  clear_operation();
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* MetricsConfigurationRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<MetricsConfigurationRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.MetricsConfig changes = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::MetricsConfig::_InternalParse;
        object = msg->mutable_changes();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // bool reset_to_default = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 24) goto handle_unusual;
        msg->set_reset_to_default(::google::protobuf::internal::ReadVarint(&ptr));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool MetricsConfigurationRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.MetricsConfig changes = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_changes()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // bool reset_to_default = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (24 & 0xFF)) {
          clear_operation();
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
                 input, &operation_.reset_to_default_)));
          set_has_reset_to_default();
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void MetricsConfigurationRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // .dmi.MetricsConfig changes = 2;
  if (has_changes()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, HasBitSetters::changes(this), output);
  }

  // bool reset_to_default = 3;
  if (has_reset_to_default()) {
    ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->reset_to_default(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationRequest)
}

::google::protobuf::uint8* MetricsConfigurationRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // .dmi.MetricsConfig changes = 2;
  if (has_changes()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        2, HasBitSetters::changes(this), target);
  }

  // bool reset_to_default = 3;
  if (has_reset_to_default()) {
    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->reset_to_default(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationRequest)
  return target;
}

size_t MetricsConfigurationRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  switch (operation_case()) {
    // .dmi.MetricsConfig changes = 2;
    case kChanges: {
      total_size += 1 +
        ::google::protobuf::internal::WireFormatLite::MessageSize(
          *operation_.changes_);
      break;
    }
    // bool reset_to_default = 3;
    case kResetToDefault: {
      total_size += 1 + 1;
      break;
    }
    case OPERATION_NOT_SET: {
      break;
    }
  }
  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void MetricsConfigurationRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const MetricsConfigurationRequest* source =
      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationRequest)
    MergeFrom(*source);
  }
}

void MetricsConfigurationRequest::MergeFrom(const MetricsConfigurationRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
  switch (from.operation_case()) {
    case kChanges: {
      mutable_changes()->::dmi::MetricsConfig::MergeFrom(from.changes());
      break;
    }
    case kResetToDefault: {
      set_reset_to_default(from.reset_to_default());
      break;
    }
    case OPERATION_NOT_SET: {
      break;
    }
  }
}

void MetricsConfigurationRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void MetricsConfigurationRequest::CopyFrom(const MetricsConfigurationRequest& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool MetricsConfigurationRequest::IsInitialized() const {
  return true;
}

void MetricsConfigurationRequest::Swap(MetricsConfigurationRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void MetricsConfigurationRequest::InternalSwap(MetricsConfigurationRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(device_uuid_, other->device_uuid_);
  swap(operation_, other->operation_);
  swap(_oneof_case_[0], other->_oneof_case_[0]);
}

::google::protobuf::Metadata MetricsConfigurationRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void MetricsConfigurationResponse::InitAsDefaultInstance() {
}
class MetricsConfigurationResponse::HasBitSetters {
 public:
};

#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int MetricsConfigurationResponse::kStatusFieldNumber;
const int MetricsConfigurationResponse::kReasonFieldNumber;
const int MetricsConfigurationResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

MetricsConfigurationResponse::MetricsConfigurationResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.MetricsConfigurationResponse)
}
MetricsConfigurationResponse::MetricsConfigurationResponse(const MetricsConfigurationResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.MetricsConfigurationResponse)
}

void MetricsConfigurationResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
}

MetricsConfigurationResponse::~MetricsConfigurationResponse() {
  // @@protoc_insertion_point(destructor:dmi.MetricsConfigurationResponse)
  SharedDtor();
}

void MetricsConfigurationResponse::SharedDtor() {
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
}

void MetricsConfigurationResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const MetricsConfigurationResponse& MetricsConfigurationResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_MetricsConfigurationResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void MetricsConfigurationResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.MetricsConfigurationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* MetricsConfigurationResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<MetricsConfigurationResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::MetricsConfigurationResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // string reason_detail = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.MetricsConfigurationResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool MetricsConfigurationResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.MetricsConfigurationResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.MetricsConfigurationResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::MetricsConfigurationResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.MetricsConfigurationResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.MetricsConfigurationResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.MetricsConfigurationResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void MetricsConfigurationResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.MetricsConfigurationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.MetricsConfigurationResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.MetricsConfigurationResponse)
}

::google::protobuf::uint8* MetricsConfigurationResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricsConfigurationResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.MetricsConfigurationResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        3, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricsConfigurationResponse)
  return target;
}

size_t MetricsConfigurationResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.MetricsConfigurationResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string reason_detail = 3;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.MetricsConfigurationResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void MetricsConfigurationResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricsConfigurationResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const MetricsConfigurationResponse* source =
      ::google::protobuf::DynamicCastToGenerated<MetricsConfigurationResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricsConfigurationResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricsConfigurationResponse)
    MergeFrom(*source);
  }
}

void MetricsConfigurationResponse::MergeFrom(const MetricsConfigurationResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricsConfigurationResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void MetricsConfigurationResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricsConfigurationResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void MetricsConfigurationResponse::CopyFrom(const MetricsConfigurationResponse& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricsConfigurationResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool MetricsConfigurationResponse::IsInitialized() const {
  return true;
}

void MetricsConfigurationResponse::Swap(MetricsConfigurationResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void MetricsConfigurationResponse::InternalSwap(MetricsConfigurationResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata MetricsConfigurationResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void MetricMetaData::InitAsDefaultInstance() {
  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->device_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
  ::dmi::_MetricMetaData_default_instance_._instance.get_mutable()->component_uuid_ = const_cast< ::dmi::Uuid*>(
      ::dmi::Uuid::internal_default_instance());
}
class MetricMetaData::HasBitSetters {
 public:
  static const ::dmi::Uuid& device_uuid(const MetricMetaData* msg);
  static const ::dmi::Uuid& component_uuid(const MetricMetaData* msg);
};

const ::dmi::Uuid&
MetricMetaData::HasBitSetters::device_uuid(const MetricMetaData* msg) {
  return *msg->device_uuid_;
}
const ::dmi::Uuid&
MetricMetaData::HasBitSetters::component_uuid(const MetricMetaData* msg) {
  return *msg->component_uuid_;
}
void MetricMetaData::clear_device_uuid() {
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
}
void MetricMetaData::clear_component_uuid() {
  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
    delete component_uuid_;
  }
  component_uuid_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int MetricMetaData::kDeviceUuidFieldNumber;
const int MetricMetaData::kComponentUuidFieldNumber;
const int MetricMetaData::kComponentNameFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

MetricMetaData::MetricMetaData()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.MetricMetaData)
}
MetricMetaData::MetricMetaData(const MetricMetaData& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.component_name().size() > 0) {
    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
  }
  if (from.has_device_uuid()) {
    device_uuid_ = new ::dmi::Uuid(*from.device_uuid_);
  } else {
    device_uuid_ = nullptr;
  }
  if (from.has_component_uuid()) {
    component_uuid_ = new ::dmi::Uuid(*from.component_uuid_);
  } else {
    component_uuid_ = nullptr;
  }
  // @@protoc_insertion_point(copy_constructor:dmi.MetricMetaData)
}

void MetricMetaData::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  component_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&device_uuid_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&component_uuid_) -
      reinterpret_cast<char*>(&device_uuid_)) + sizeof(component_uuid_));
}

MetricMetaData::~MetricMetaData() {
  // @@protoc_insertion_point(destructor:dmi.MetricMetaData)
  SharedDtor();
}

void MetricMetaData::SharedDtor() {
  component_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete device_uuid_;
  if (this != internal_default_instance()) delete component_uuid_;
}

void MetricMetaData::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const MetricMetaData& MetricMetaData::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_MetricMetaData_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void MetricMetaData::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.MetricMetaData)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  component_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && device_uuid_ != nullptr) {
    delete device_uuid_;
  }
  device_uuid_ = nullptr;
  if (GetArenaNoVirtual() == nullptr && component_uuid_ != nullptr) {
    delete component_uuid_;
  }
  component_uuid_ = nullptr;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* MetricMetaData::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<MetricMetaData*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_device_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.Uuid component_uuid = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Uuid::_InternalParse;
        object = msg->mutable_component_uuid();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string component_name = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.MetricMetaData.component_name");
        object = msg->mutable_component_name();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool MetricMetaData::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.MetricMetaData)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Uuid device_uuid = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_device_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.Uuid component_uuid = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_component_uuid()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string component_name = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_component_name()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->component_name().data(), static_cast<int>(this->component_name().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.MetricMetaData.component_name"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.MetricMetaData)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.MetricMetaData)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void MetricMetaData::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.MetricMetaData)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::device_uuid(this), output);
  }

  // .dmi.Uuid component_uuid = 2;
  if (this->has_component_uuid()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, HasBitSetters::component_uuid(this), output);
  }

  // string component_name = 3;
  if (this->component_name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->component_name().data(), static_cast<int>(this->component_name().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.MetricMetaData.component_name");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      3, this->component_name(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.MetricMetaData)
}

::google::protobuf::uint8* MetricMetaData::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.MetricMetaData)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::device_uuid(this), target);
  }

  // .dmi.Uuid component_uuid = 2;
  if (this->has_component_uuid()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        2, HasBitSetters::component_uuid(this), target);
  }

  // string component_name = 3;
  if (this->component_name().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->component_name().data(), static_cast<int>(this->component_name().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.MetricMetaData.component_name");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        3, this->component_name(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.MetricMetaData)
  return target;
}

size_t MetricMetaData::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.MetricMetaData)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string component_name = 3;
  if (this->component_name().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->component_name());
  }

  // .dmi.Uuid device_uuid = 1;
  if (this->has_device_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *device_uuid_);
  }

  // .dmi.Uuid component_uuid = 2;
  if (this->has_component_uuid()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *component_uuid_);
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void MetricMetaData::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.MetricMetaData)
  GOOGLE_DCHECK_NE(&from, this);
  const MetricMetaData* source =
      ::google::protobuf::DynamicCastToGenerated<MetricMetaData>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.MetricMetaData)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.MetricMetaData)
    MergeFrom(*source);
  }
}

void MetricMetaData::MergeFrom(const MetricMetaData& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.MetricMetaData)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.component_name().size() > 0) {

    component_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.component_name_);
  }
  if (from.has_device_uuid()) {
    mutable_device_uuid()->::dmi::Uuid::MergeFrom(from.device_uuid());
  }
  if (from.has_component_uuid()) {
    mutable_component_uuid()->::dmi::Uuid::MergeFrom(from.component_uuid());
  }
}

void MetricMetaData::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.MetricMetaData)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void MetricMetaData::CopyFrom(const MetricMetaData& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.MetricMetaData)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool MetricMetaData::IsInitialized() const {
  return true;
}

void MetricMetaData::Swap(MetricMetaData* other) {
  if (other == this) return;
  InternalSwap(other);
}
void MetricMetaData::InternalSwap(MetricMetaData* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  component_name_.Swap(&other->component_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(device_uuid_, other->device_uuid_);
  swap(component_uuid_, other->component_uuid_);
}

::google::protobuf::Metadata MetricMetaData::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void Metric::InitAsDefaultInstance() {
  ::dmi::_Metric_default_instance_._instance.get_mutable()->metric_metadata_ = const_cast< ::dmi::MetricMetaData*>(
      ::dmi::MetricMetaData::internal_default_instance());
  ::dmi::_Metric_default_instance_._instance.get_mutable()->value_ = const_cast< ::dmi::ComponentSensorData*>(
      ::dmi::ComponentSensorData::internal_default_instance());
}
class Metric::HasBitSetters {
 public:
  static const ::dmi::MetricMetaData& metric_metadata(const Metric* msg);
  static const ::dmi::ComponentSensorData& value(const Metric* msg);
};

const ::dmi::MetricMetaData&
Metric::HasBitSetters::metric_metadata(const Metric* msg) {
  return *msg->metric_metadata_;
}
const ::dmi::ComponentSensorData&
Metric::HasBitSetters::value(const Metric* msg) {
  return *msg->value_;
}
void Metric::clear_value() {
  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
    delete value_;
  }
  value_ = nullptr;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int Metric::kMetricIdFieldNumber;
const int Metric::kMetricMetadataFieldNumber;
const int Metric::kValueFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

Metric::Metric()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.Metric)
}
Metric::Metric(const Metric& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  if (from.has_metric_metadata()) {
    metric_metadata_ = new ::dmi::MetricMetaData(*from.metric_metadata_);
  } else {
    metric_metadata_ = nullptr;
  }
  if (from.has_value()) {
    value_ = new ::dmi::ComponentSensorData(*from.value_);
  } else {
    value_ = nullptr;
  }
  metric_id_ = from.metric_id_;
  // @@protoc_insertion_point(copy_constructor:dmi.Metric)
}

void Metric::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::memset(&metric_metadata_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&metric_id_) -
      reinterpret_cast<char*>(&metric_metadata_)) + sizeof(metric_id_));
}

Metric::~Metric() {
  // @@protoc_insertion_point(destructor:dmi.Metric)
  SharedDtor();
}

void Metric::SharedDtor() {
  if (this != internal_default_instance()) delete metric_metadata_;
  if (this != internal_default_instance()) delete value_;
}

void Metric::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const Metric& Metric::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_Metric_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void Metric::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.Metric)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  if (GetArenaNoVirtual() == nullptr && metric_metadata_ != nullptr) {
    delete metric_metadata_;
  }
  metric_metadata_ = nullptr;
  if (GetArenaNoVirtual() == nullptr && value_ != nullptr) {
    delete value_;
  }
  value_ = nullptr;
  metric_id_ = 0;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* Metric::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<Metric*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.MetricNames metric_id = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.MetricMetaData metric_metadata = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 18) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
        object = msg->mutable_metric_metadata();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.ComponentSensorData value = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::ComponentSensorData::_InternalParse;
        object = msg->mutable_value();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool Metric::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.Metric)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.MetricNames metric_id = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_metric_id(static_cast< ::dmi::MetricNames >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.MetricMetaData metric_metadata = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (18 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_metric_metadata()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.ComponentSensorData value = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_value()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.Metric)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.Metric)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void Metric::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.Metric)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->metric_id(), output);
  }

  // .dmi.MetricMetaData metric_metadata = 2;
  if (this->has_metric_metadata()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      2, HasBitSetters::metric_metadata(this), output);
  }

  // .dmi.ComponentSensorData value = 3;
  if (this->has_value()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, HasBitSetters::value(this), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.Metric)
}

::google::protobuf::uint8* Metric::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.Metric)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->metric_id(), target);
  }

  // .dmi.MetricMetaData metric_metadata = 2;
  if (this->has_metric_metadata()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        2, HasBitSetters::metric_metadata(this), target);
  }

  // .dmi.ComponentSensorData value = 3;
  if (this->has_value()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        3, HasBitSetters::value(this), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.Metric)
  return target;
}

size_t Metric::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.Metric)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.MetricMetaData metric_metadata = 2;
  if (this->has_metric_metadata()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *metric_metadata_);
  }

  // .dmi.ComponentSensorData value = 3;
  if (this->has_value()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *value_);
  }

  // .dmi.MetricNames metric_id = 1;
  if (this->metric_id() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void Metric::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.Metric)
  GOOGLE_DCHECK_NE(&from, this);
  const Metric* source =
      ::google::protobuf::DynamicCastToGenerated<Metric>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.Metric)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.Metric)
    MergeFrom(*source);
  }
}

void Metric::MergeFrom(const Metric& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.Metric)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.has_metric_metadata()) {
    mutable_metric_metadata()->::dmi::MetricMetaData::MergeFrom(from.metric_metadata());
  }
  if (from.has_value()) {
    mutable_value()->::dmi::ComponentSensorData::MergeFrom(from.value());
  }
  if (from.metric_id() != 0) {
    set_metric_id(from.metric_id());
  }
}

void Metric::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.Metric)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void Metric::CopyFrom(const Metric& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.Metric)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool Metric::IsInitialized() const {
  return true;
}

void Metric::Swap(Metric* other) {
  if (other == this) return;
  InternalSwap(other);
}
void Metric::InternalSwap(Metric* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(metric_metadata_, other->metric_metadata_);
  swap(value_, other->value_);
  swap(metric_id_, other->metric_id_);
}

::google::protobuf::Metadata Metric::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void GetMetricRequest::InitAsDefaultInstance() {
  ::dmi::_GetMetricRequest_default_instance_._instance.get_mutable()->meta_data_ = const_cast< ::dmi::MetricMetaData*>(
      ::dmi::MetricMetaData::internal_default_instance());
}
class GetMetricRequest::HasBitSetters {
 public:
  static const ::dmi::MetricMetaData& meta_data(const GetMetricRequest* msg);
};

const ::dmi::MetricMetaData&
GetMetricRequest::HasBitSetters::meta_data(const GetMetricRequest* msg) {
  return *msg->meta_data_;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int GetMetricRequest::kMetaDataFieldNumber;
const int GetMetricRequest::kMetricIdFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

GetMetricRequest::GetMetricRequest()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.GetMetricRequest)
}
GetMetricRequest::GetMetricRequest(const GetMetricRequest& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  if (from.has_meta_data()) {
    meta_data_ = new ::dmi::MetricMetaData(*from.meta_data_);
  } else {
    meta_data_ = nullptr;
  }
  metric_id_ = from.metric_id_;
  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricRequest)
}

void GetMetricRequest::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  ::memset(&meta_data_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&metric_id_) -
      reinterpret_cast<char*>(&meta_data_)) + sizeof(metric_id_));
}

GetMetricRequest::~GetMetricRequest() {
  // @@protoc_insertion_point(destructor:dmi.GetMetricRequest)
  SharedDtor();
}

void GetMetricRequest::SharedDtor() {
  if (this != internal_default_instance()) delete meta_data_;
}

void GetMetricRequest::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const GetMetricRequest& GetMetricRequest::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricRequest_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void GetMetricRequest::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.GetMetricRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  if (GetArenaNoVirtual() == nullptr && meta_data_ != nullptr) {
    delete meta_data_;
  }
  meta_data_ = nullptr;
  metric_id_ = 0;
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* GetMetricRequest::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<GetMetricRequest*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.MetricMetaData meta_data = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 10) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::MetricMetaData::_InternalParse;
        object = msg->mutable_meta_data();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // .dmi.MetricNames metric_id = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_metric_id(static_cast<::dmi::MetricNames>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool GetMetricRequest::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.GetMetricRequest)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.MetricMetaData meta_data = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (10 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_meta_data()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.MetricNames metric_id = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_metric_id(static_cast< ::dmi::MetricNames >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.GetMetricRequest)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.GetMetricRequest)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void GetMetricRequest::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.GetMetricRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricMetaData meta_data = 1;
  if (this->has_meta_data()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      1, HasBitSetters::meta_data(this), output);
  }

  // .dmi.MetricNames metric_id = 2;
  if (this->metric_id() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->metric_id(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.GetMetricRequest)
}

::google::protobuf::uint8* GetMetricRequest::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricRequest)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.MetricMetaData meta_data = 1;
  if (this->has_meta_data()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        1, HasBitSetters::meta_data(this), target);
  }

  // .dmi.MetricNames metric_id = 2;
  if (this->metric_id() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->metric_id(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricRequest)
  return target;
}

size_t GetMetricRequest::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricRequest)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // .dmi.MetricMetaData meta_data = 1;
  if (this->has_meta_data()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *meta_data_);
  }

  // .dmi.MetricNames metric_id = 2;
  if (this->metric_id() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->metric_id());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void GetMetricRequest::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricRequest)
  GOOGLE_DCHECK_NE(&from, this);
  const GetMetricRequest* source =
      ::google::protobuf::DynamicCastToGenerated<GetMetricRequest>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricRequest)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricRequest)
    MergeFrom(*source);
  }
}

void GetMetricRequest::MergeFrom(const GetMetricRequest& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricRequest)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.has_meta_data()) {
    mutable_meta_data()->::dmi::MetricMetaData::MergeFrom(from.meta_data());
  }
  if (from.metric_id() != 0) {
    set_metric_id(from.metric_id());
  }
}

void GetMetricRequest::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void GetMetricRequest::CopyFrom(const GetMetricRequest& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricRequest)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool GetMetricRequest::IsInitialized() const {
  return true;
}

void GetMetricRequest::Swap(GetMetricRequest* other) {
  if (other == this) return;
  InternalSwap(other);
}
void GetMetricRequest::InternalSwap(GetMetricRequest* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  swap(meta_data_, other->meta_data_);
  swap(metric_id_, other->metric_id_);
}

::google::protobuf::Metadata GetMetricRequest::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


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

void GetMetricResponse::InitAsDefaultInstance() {
  ::dmi::_GetMetricResponse_default_instance_._instance.get_mutable()->metric_ = const_cast< ::dmi::Metric*>(
      ::dmi::Metric::internal_default_instance());
}
class GetMetricResponse::HasBitSetters {
 public:
  static const ::dmi::Metric& metric(const GetMetricResponse* msg);
};

const ::dmi::Metric&
GetMetricResponse::HasBitSetters::metric(const GetMetricResponse* msg) {
  return *msg->metric_;
}
#if !defined(_MSC_VER) || _MSC_VER >= 1900
const int GetMetricResponse::kStatusFieldNumber;
const int GetMetricResponse::kReasonFieldNumber;
const int GetMetricResponse::kMetricFieldNumber;
const int GetMetricResponse::kReasonDetailFieldNumber;
#endif  // !defined(_MSC_VER) || _MSC_VER >= 1900

GetMetricResponse::GetMetricResponse()
  : ::google::protobuf::Message(), _internal_metadata_(nullptr) {
  SharedCtor();
  // @@protoc_insertion_point(constructor:dmi.GetMetricResponse)
}
GetMetricResponse::GetMetricResponse(const GetMetricResponse& from)
  : ::google::protobuf::Message(),
      _internal_metadata_(nullptr) {
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (from.reason_detail().size() > 0) {
    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_metric()) {
    metric_ = new ::dmi::Metric(*from.metric_);
  } else {
    metric_ = nullptr;
  }
  ::memcpy(&status_, &from.status_,
    static_cast<size_t>(reinterpret_cast<char*>(&reason_) -
    reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  // @@protoc_insertion_point(copy_constructor:dmi.GetMetricResponse)
}

void GetMetricResponse::SharedCtor() {
  ::google::protobuf::internal::InitSCC(
      &scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  reason_detail_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  ::memset(&metric_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&metric_)) + sizeof(reason_));
}

GetMetricResponse::~GetMetricResponse() {
  // @@protoc_insertion_point(destructor:dmi.GetMetricResponse)
  SharedDtor();
}

void GetMetricResponse::SharedDtor() {
  reason_detail_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (this != internal_default_instance()) delete metric_;
}

void GetMetricResponse::SetCachedSize(int size) const {
  _cached_size_.Set(size);
}
const GetMetricResponse& GetMetricResponse::default_instance() {
  ::google::protobuf::internal::InitSCC(&::scc_info_GetMetricResponse_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto.base);
  return *internal_default_instance();
}


void GetMetricResponse::Clear() {
// @@protoc_insertion_point(message_clear_start:dmi.GetMetricResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  reason_detail_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
  if (GetArenaNoVirtual() == nullptr && metric_ != nullptr) {
    delete metric_;
  }
  metric_ = nullptr;
  ::memset(&status_, 0, static_cast<size_t>(
      reinterpret_cast<char*>(&reason_) -
      reinterpret_cast<char*>(&status_)) + sizeof(reason_));
  _internal_metadata_.Clear();
}

#if GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
const char* GetMetricResponse::_InternalParse(const char* begin, const char* end, void* object,
                  ::google::protobuf::internal::ParseContext* ctx) {
  auto msg = static_cast<GetMetricResponse*>(object);
  ::google::protobuf::int32 size; (void)size;
  int depth; (void)depth;
  ::google::protobuf::uint32 tag;
  ::google::protobuf::internal::ParseFunc parser_till_end; (void)parser_till_end;
  auto ptr = begin;
  while (ptr < end) {
    ptr = ::google::protobuf::io::Parse32(ptr, &tag);
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
    switch (tag >> 3) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast<::google::protobuf::uint8>(tag) != 8) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_status(static_cast<::dmi::Status>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.GetMetricResponse.Reason reason = 2;
      case 2: {
        if (static_cast<::google::protobuf::uint8>(tag) != 16) goto handle_unusual;
        ::google::protobuf::uint64 val = ::google::protobuf::internal::ReadVarint(&ptr);
        msg->set_reason(static_cast<::dmi::GetMetricResponse_Reason>(val));
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        break;
      }
      // .dmi.Metric metric = 3;
      case 3: {
        if (static_cast<::google::protobuf::uint8>(tag) != 26) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        parser_till_end = ::dmi::Metric::_InternalParse;
        object = msg->mutable_metric();
        if (size > end - ptr) goto len_delim_till_end;
        ptr += size;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ctx->ParseExactRange(
            {parser_till_end, object}, ptr - size, ptr));
        break;
      }
      // string reason_detail = 4;
      case 4: {
        if (static_cast<::google::protobuf::uint8>(tag) != 34) goto handle_unusual;
        ptr = ::google::protobuf::io::ReadSize(ptr, &size);
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
        ctx->extra_parse_data().SetFieldName("dmi.GetMetricResponse.reason_detail");
        object = msg->mutable_reason_detail();
        if (size > end - ptr + ::google::protobuf::internal::ParseContext::kSlopBytes) {
          parser_till_end = ::google::protobuf::internal::GreedyStringParserUTF8;
          goto string_till_end;
        }
        GOOGLE_PROTOBUF_PARSER_ASSERT(::google::protobuf::internal::StringCheckUTF8(ptr, size, ctx));
        ::google::protobuf::internal::InlineGreedyStringParser(object, ptr, size, ctx);
        ptr += size;
        break;
      }
      default: {
      handle_unusual:
        if ((tag & 7) == 4 || tag == 0) {
          ctx->EndGroup(tag);
          return ptr;
        }
        auto res = UnknownFieldParse(tag, {_InternalParse, msg},
          ptr, end, msg->_internal_metadata_.mutable_unknown_fields(), ctx);
        ptr = res.first;
        GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
        if (res.second) return ptr;
      }
    }  // switch
  }  // while
  return ptr;
string_till_end:
  static_cast<::std::string*>(object)->clear();
  static_cast<::std::string*>(object)->reserve(size);
  goto len_delim_till_end;
len_delim_till_end:
  return ctx->StoreAndTailCall(ptr, end, {_InternalParse, msg},
                               {parser_till_end, object}, size);
}
#else  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER
bool GetMetricResponse::MergePartialFromCodedStream(
    ::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!PROTOBUF_PREDICT_TRUE(EXPRESSION)) goto failure
  ::google::protobuf::uint32 tag;
  // @@protoc_insertion_point(parse_start:dmi.GetMetricResponse)
  for (;;) {
    ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
    tag = p.first;
    if (!p.second) goto handle_unusual;
    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
      // .dmi.Status status = 1;
      case 1: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (8 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_status(static_cast< ::dmi::Status >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.GetMetricResponse.Reason reason = 2;
      case 2: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (16 & 0xFF)) {
          int value = 0;
          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
                   int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
                 input, &value)));
          set_reason(static_cast< ::dmi::GetMetricResponse_Reason >(value));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // .dmi.Metric metric = 3;
      case 3: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (26 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadMessage(
               input, mutable_metric()));
        } else {
          goto handle_unusual;
        }
        break;
      }

      // string reason_detail = 4;
      case 4: {
        if (static_cast< ::google::protobuf::uint8>(tag) == (34 & 0xFF)) {
          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
                input, this->mutable_reason_detail()));
          DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
            this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
            ::google::protobuf::internal::WireFormatLite::PARSE,
            "dmi.GetMetricResponse.reason_detail"));
        } else {
          goto handle_unusual;
        }
        break;
      }

      default: {
      handle_unusual:
        if (tag == 0) {
          goto success;
        }
        DO_(::google::protobuf::internal::WireFormat::SkipField(
              input, tag, _internal_metadata_.mutable_unknown_fields()));
        break;
      }
    }
  }
success:
  // @@protoc_insertion_point(parse_success:dmi.GetMetricResponse)
  return true;
failure:
  // @@protoc_insertion_point(parse_failure:dmi.GetMetricResponse)
  return false;
#undef DO_
}
#endif  // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER

void GetMetricResponse::SerializeWithCachedSizes(
    ::google::protobuf::io::CodedOutputStream* output) const {
  // @@protoc_insertion_point(serialize_start:dmi.GetMetricResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      1, this->status(), output);
  }

  // .dmi.GetMetricResponse.Reason reason = 2;
  if (this->reason() != 0) {
    ::google::protobuf::internal::WireFormatLite::WriteEnum(
      2, this->reason(), output);
  }

  // .dmi.Metric metric = 3;
  if (this->has_metric()) {
    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
      3, HasBitSetters::metric(this), output);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.GetMetricResponse.reason_detail");
    ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased(
      4, this->reason_detail(), output);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
        _internal_metadata_.unknown_fields(), output);
  }
  // @@protoc_insertion_point(serialize_end:dmi.GetMetricResponse)
}

::google::protobuf::uint8* GetMetricResponse::InternalSerializeWithCachedSizesToArray(
    ::google::protobuf::uint8* target) const {
  // @@protoc_insertion_point(serialize_to_array_start:dmi.GetMetricResponse)
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      1, this->status(), target);
  }

  // .dmi.GetMetricResponse.Reason reason = 2;
  if (this->reason() != 0) {
    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
      2, this->reason(), target);
  }

  // .dmi.Metric metric = 3;
  if (this->has_metric()) {
    target = ::google::protobuf::internal::WireFormatLite::
      InternalWriteMessageToArray(
        3, HasBitSetters::metric(this), target);
  }

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    ::google::protobuf::internal::WireFormatLite::VerifyUtf8String(
      this->reason_detail().data(), static_cast<int>(this->reason_detail().length()),
      ::google::protobuf::internal::WireFormatLite::SERIALIZE,
      "dmi.GetMetricResponse.reason_detail");
    target =
      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
        4, this->reason_detail(), target);
  }

  if (_internal_metadata_.have_unknown_fields()) {
    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
        _internal_metadata_.unknown_fields(), target);
  }
  // @@protoc_insertion_point(serialize_to_array_end:dmi.GetMetricResponse)
  return target;
}

size_t GetMetricResponse::ByteSizeLong() const {
// @@protoc_insertion_point(message_byte_size_start:dmi.GetMetricResponse)
  size_t total_size = 0;

  if (_internal_metadata_.have_unknown_fields()) {
    total_size +=
      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
        _internal_metadata_.unknown_fields());
  }
  ::google::protobuf::uint32 cached_has_bits = 0;
  // Prevent compiler warnings about cached_has_bits being unused
  (void) cached_has_bits;

  // string reason_detail = 4;
  if (this->reason_detail().size() > 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::StringSize(
        this->reason_detail());
  }

  // .dmi.Metric metric = 3;
  if (this->has_metric()) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::MessageSize(
        *metric_);
  }

  // .dmi.Status status = 1;
  if (this->status() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->status());
  }

  // .dmi.GetMetricResponse.Reason reason = 2;
  if (this->reason() != 0) {
    total_size += 1 +
      ::google::protobuf::internal::WireFormatLite::EnumSize(this->reason());
  }

  int cached_size = ::google::protobuf::internal::ToCachedSize(total_size);
  SetCachedSize(cached_size);
  return total_size;
}

void GetMetricResponse::MergeFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_merge_from_start:dmi.GetMetricResponse)
  GOOGLE_DCHECK_NE(&from, this);
  const GetMetricResponse* source =
      ::google::protobuf::DynamicCastToGenerated<GetMetricResponse>(
          &from);
  if (source == nullptr) {
  // @@protoc_insertion_point(generalized_merge_from_cast_fail:dmi.GetMetricResponse)
    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
  } else {
  // @@protoc_insertion_point(generalized_merge_from_cast_success:dmi.GetMetricResponse)
    MergeFrom(*source);
  }
}

void GetMetricResponse::MergeFrom(const GetMetricResponse& from) {
// @@protoc_insertion_point(class_specific_merge_from_start:dmi.GetMetricResponse)
  GOOGLE_DCHECK_NE(&from, this);
  _internal_metadata_.MergeFrom(from._internal_metadata_);
  ::google::protobuf::uint32 cached_has_bits = 0;
  (void) cached_has_bits;

  if (from.reason_detail().size() > 0) {

    reason_detail_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.reason_detail_);
  }
  if (from.has_metric()) {
    mutable_metric()->::dmi::Metric::MergeFrom(from.metric());
  }
  if (from.status() != 0) {
    set_status(from.status());
  }
  if (from.reason() != 0) {
    set_reason(from.reason());
  }
}

void GetMetricResponse::CopyFrom(const ::google::protobuf::Message& from) {
// @@protoc_insertion_point(generalized_copy_from_start:dmi.GetMetricResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

void GetMetricResponse::CopyFrom(const GetMetricResponse& from) {
// @@protoc_insertion_point(class_specific_copy_from_start:dmi.GetMetricResponse)
  if (&from == this) return;
  Clear();
  MergeFrom(from);
}

bool GetMetricResponse::IsInitialized() const {
  return true;
}

void GetMetricResponse::Swap(GetMetricResponse* other) {
  if (other == this) return;
  InternalSwap(other);
}
void GetMetricResponse::InternalSwap(GetMetricResponse* other) {
  using std::swap;
  _internal_metadata_.Swap(&other->_internal_metadata_);
  reason_detail_.Swap(&other->reason_detail_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(),
    GetArenaNoVirtual());
  swap(metric_, other->metric_);
  swap(status_, other->status_);
  swap(reason_, other->reason_);
}

::google::protobuf::Metadata GetMetricResponse::GetMetadata() const {
  ::google::protobuf::internal::AssignDescriptors(&::assign_descriptors_table_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto);
  return ::file_level_metadata_dmi_2fhw_5fmetrics_5fmgmt_5fservice_2eproto[kIndexInFileMessages];
}


// @@protoc_insertion_point(namespace_scope)
}  // namespace dmi
namespace google {
namespace protobuf {
template<> PROTOBUF_NOINLINE ::dmi::MetricConfig* Arena::CreateMaybeMessage< ::dmi::MetricConfig >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::MetricConfig >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::MetricsConfig* Arena::CreateMaybeMessage< ::dmi::MetricsConfig >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::MetricsConfig >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::ListMetricsResponse* Arena::CreateMaybeMessage< ::dmi::ListMetricsResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::ListMetricsResponse >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationRequest* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::MetricsConfigurationRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::MetricsConfigurationResponse* Arena::CreateMaybeMessage< ::dmi::MetricsConfigurationResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::MetricsConfigurationResponse >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::MetricMetaData* Arena::CreateMaybeMessage< ::dmi::MetricMetaData >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::MetricMetaData >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::Metric* Arena::CreateMaybeMessage< ::dmi::Metric >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::Metric >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::GetMetricRequest* Arena::CreateMaybeMessage< ::dmi::GetMetricRequest >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::GetMetricRequest >(arena);
}
template<> PROTOBUF_NOINLINE ::dmi::GetMetricResponse* Arena::CreateMaybeMessage< ::dmi::GetMetricResponse >(Arena* arena) {
  return Arena::CreateInternal< ::dmi::GetMetricResponse >(arena);
}
}  // namespace protobuf
}  // namespace google

// @@protoc_insertion_point(global_scope)
#include <google/protobuf/port_undef.inc>
