// Copyright (c) 2019, 2021 by Robert Bosch GmbH. All rights reserved. // Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_posh/capro/service_description.hpp" #include "iceoryx_hoofs/cxx/convert.hpp" #include namespace iox { namespace capro { ServiceDescription::ClassHash::ClassHash() noexcept : ClassHash{0U, 0U, 0U, 0U} { } ServiceDescription::ClassHash::ClassHash(const std::initializer_list& values) noexcept { uint64_t index = 0U; for (auto& v : values) { data[index++] = v; if (index == CLASS_HASH_ELEMENT_COUNT) { return; } } } uint32_t& ServiceDescription::ClassHash::operator[](iox::cxx::range index) noexcept { return data[index]; } const uint32_t& ServiceDescription::ClassHash::operator[]( iox::cxx::range index) const noexcept { return data[index]; } bool ServiceDescription::ClassHash::operator==(const ClassHash& rhs) const noexcept { for (size_t i = 0U; i < CLASS_HASH_ELEMENT_COUNT; ++i) { if (data[i] != rhs[i]) { return false; } } return true; } bool ServiceDescription::ClassHash::operator!=(const ClassHash& rhs) const noexcept { return !operator==(rhs); } ServiceDescription::ServiceDescription() noexcept : ServiceDescription("", "", "") { } ServiceDescription::ServiceDescription(const IdString_t& service, const IdString_t& instance, const IdString_t& event, ClassHash classHash, Interfaces interfaceSource) noexcept : m_serviceString{service} , m_instanceString{instance} , m_eventString{event} , m_classHash(classHash) , m_interfaceSource(interfaceSource) { } bool ServiceDescription::operator==(const ServiceDescription& rhs) const noexcept { if (m_serviceString != rhs.m_serviceString) { return false; } if (m_instanceString != rhs.m_instanceString) { return false; } if (m_eventString != rhs.m_eventString) { return false; } return true; } bool ServiceDescription::operator!=(const ServiceDescription& rhs) const noexcept { return !(*this == rhs); } bool ServiceDescription::operator<(const ServiceDescription& rhs) const noexcept { auto serviceCompare = m_serviceString.compare(rhs.m_serviceString); if (serviceCompare != 0) { return 0 < serviceCompare; } auto instanceCompare = m_instanceString.compare(rhs.m_instanceString); if (instanceCompare != 0) { return 0 < instanceCompare; } auto eventCompare = m_eventString.compare(rhs.m_eventString); if (eventCompare != 0) { return 0 < eventCompare; } return false; } ServiceDescription::operator cxx::Serialization() const noexcept { std::underlying_type::type scope = static_cast::type>(m_scope); std::underlying_type::type interface = static_cast::type>(m_interfaceSource); return cxx::Serialization::create(m_serviceString, m_instanceString, m_eventString, m_classHash[0U], m_classHash[1U], m_classHash[2U], m_classHash[3U], scope, interface); } cxx::expected ServiceDescription::deserialize(const cxx::Serialization& serialized) noexcept { ServiceDescription deserializedObject; using ScopeUnderlyingType = std::underlying_type::type; using InterfaceUnderlyingType = std::underlying_type::type; ScopeUnderlyingType scope{0}; InterfaceUnderlyingType interfaceSource{0}; auto deserializationSuccessful = serialized.extract(deserializedObject.m_serviceString, deserializedObject.m_instanceString, deserializedObject.m_eventString, deserializedObject.m_classHash[0U], deserializedObject.m_classHash[1U], deserializedObject.m_classHash[2U], deserializedObject.m_classHash[3U], scope, interfaceSource); if (!deserializationSuccessful || scope >= static_cast(Scope::INVALID) || interfaceSource >= static_cast(Interfaces::INTERFACE_END)) { return cxx::error(cxx::Serialization::Error::DESERIALIZATION_FAILED); } deserializedObject.m_scope = static_cast(scope); deserializedObject.m_interfaceSource = static_cast(interfaceSource); return cxx::success(deserializedObject); } const IdString_t& ServiceDescription::getServiceIDString() const noexcept { return m_serviceString; } const IdString_t& ServiceDescription::getInstanceIDString() const noexcept { return m_instanceString; } const IdString_t& ServiceDescription::getEventIDString() const noexcept { return m_eventString; } bool ServiceDescription::isLocal() const noexcept { return m_scope == Scope::LOCAL; } void ServiceDescription::setLocal() noexcept { m_scope = Scope::LOCAL; } Scope ServiceDescription::getScope() const noexcept { return m_scope; } ServiceDescription::ClassHash ServiceDescription::getClassHash() const noexcept { return m_classHash; } Interfaces ServiceDescription::getSourceInterface() const noexcept { return m_interfaceSource; } bool serviceMatch(const ServiceDescription& first, const ServiceDescription& second) noexcept { return (first.getServiceIDString() == second.getServiceIDString()); } std::ostream& operator<<(std::ostream& stream, const ServiceDescription& service) noexcept { /// @todo #415 Add classHash, scope and interface stream << "Service: " << service.getServiceIDString() << ", Instance: " << service.getInstanceIDString() << ", Event: " << service.getEventIDString(); return stream; } log::LogStream& operator<<(log::LogStream& stream, const ServiceDescription& service) noexcept { /// @todo #415 Add classHash, scope and interface stream << "Service: " << service.getServiceIDString() << ", Instance: " << service.getInstanceIDString() << ", Event: " << service.getEventIDString(); return stream; } } // namespace capro } // namespace iox