Branch data Line data Source code
1 : : /* 2 : : * Copyright (C) 2026 by Thun Lu. All rights reserved. 3 : : * Author: Thun Lu <thun.lu@zohomail.cn> 4 : : * Repo: https://github.com/thun-res/vlink 5 : : * _ __ __ _ __ 6 : : * | | / / / / (_) ____ / /__ 7 : : * | | / / / / / / / __ \ / //_/ 8 : : * | |/ / / /___ / / / / / / / ,< 9 : : * |___/ /_____/ /_/ /_/ /_/ /_/|_| 10 : : * 11 : : * Licensed under the Apache License, Version 2.0 (the "License"); 12 : : * you may not use this file except in compliance with the License. 13 : : * You may obtain a copy of the License at 14 : : * 15 : : * http://www.apache.org/licenses/LICENSE-2.0 16 : : * 17 : : * Unless required by applicable law or agreed to in writing, software 18 : : * distributed under the License is distributed on an "AS IS" BASIS, 19 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 : : * See the License for the specific language governing permissions and 21 : : * limitations under the License. 22 : : */ 23 : : 24 : : #include "./dds_topic.h" 25 : : 26 : : #include <cstring> 27 : : #include <limits> 28 : : #include <new> 29 : : #include <utility> 30 : : 31 : : namespace vlink { 32 : : 33 : 2 : DdsCdrPubSubType::DdsCdrPubSubType(const std::string& type_name, dds::TypeSupport native_type) 34 : 2 : : native_type_(std::move(native_type)) { 35 : : #ifdef VLINK_SUPPORT_DDS_V3 36 : : set_name(type_name); 37 : : max_serialized_type_size = 38 : : native_type_ && native_type_->max_serialized_type_size >= 4U ? native_type_->max_serialized_type_size : 4U; 39 : : is_compute_key_provided = native_type_ && native_type_->is_compute_key_provided; 40 : : #else 41 [ + - ]: 2 : setName(type_name.c_str()); 42 [ - + - - ]: 2 : m_typeSize = native_type_ && native_type_->m_typeSize >= 4U ? native_type_->m_typeSize : 4U; 43 [ - + - - ]: 2 : m_isGetKeyDefined = native_type_ && native_type_->m_isGetKeyDefined; 44 : : #endif 45 : 2 : } 46 : : 47 : : #ifdef VLINK_SUPPORT_DDS_V3 48 : : bool DdsCdrPubSubType::is_compatible_data_representation(const Bytes& bytes, 49 : : dds::DataRepresentationId_t data_representation) { 50 : : if VUNLIKELY (!bytes.data() || bytes.size() < 4U) { 51 : : return false; 52 : : } 53 : : 54 : : const auto encapsulation = static_cast<uint16_t>((static_cast<uint16_t>(bytes.data()[0]) << 8U) | bytes.data()[1]); 55 : : 56 : : if (data_representation == dds::XCDR_DATA_REPRESENTATION) { 57 : : return encapsulation <= 3U; 58 : : } 59 : : if (data_representation == dds::XCDR2_DATA_REPRESENTATION) { 60 : : return encapsulation >= 6U && encapsulation <= 11U; 61 : : } 62 : : 63 : : return false; 64 : : } 65 : : 66 : : bool DdsCdrPubSubType::serialize(const void* const data, rtps::SerializedPayload_t& payload, 67 : : dds::DataRepresentationId_t data_representation) { 68 : : const auto& bytes = *static_cast<const Bytes*>(data); 69 : : 70 : : return is_compatible_data_representation(bytes, data_representation) && copy_to_payload(bytes, payload); 71 : : } 72 : : 73 : : bool DdsCdrPubSubType::deserialize(rtps::SerializedPayload_t& payload, void* data) { 74 : : return copy_from_payload(payload, *static_cast<Bytes*>(data)); 75 : : } 76 : : 77 : : uint32_t DdsCdrPubSubType::calculate_serialized_size(const void* const data, 78 : : dds::DataRepresentationId_t data_representation) { 79 : : const auto& bytes = *static_cast<const Bytes*>(data); 80 : : 81 : : if VUNLIKELY (!is_compatible_data_representation(bytes, data_representation)) { 82 : : return 0U; 83 : : } 84 : : 85 : : const auto size = bytes.size(); 86 : : 87 : : return size <= std::numeric_limits<uint32_t>::max() ? static_cast<uint32_t>(size) : 0U; 88 : : } 89 : : 90 : : bool DdsCdrPubSubType::compute_key(rtps::SerializedPayload_t& payload, rtps::InstanceHandle_t& handle, bool force_md5) { 91 : : return native_type_ && native_type_->compute_key(payload, handle, force_md5); 92 : : } 93 : : 94 : : bool DdsCdrPubSubType::compute_key(const void* const data, rtps::InstanceHandle_t& handle, bool force_md5) { 95 : : rtps::SerializedPayload_t payload; 96 : : return copy_to_payload(*static_cast<const Bytes*>(data), payload) && compute_key(payload, handle, force_md5); 97 : : } 98 : : 99 : : void* DdsCdrPubSubType::create_data() { return new Bytes; } 100 : : 101 : : void DdsCdrPubSubType::delete_data(void* data) { delete static_cast<Bytes*>(data); } 102 : : 103 : : void DdsCdrPubSubType::register_type_object_representation() { 104 : : if (native_type_) { 105 : : native_type_->register_type_object_representation(); 106 : : type_identifiers_ = native_type_->type_identifiers(); 107 : : } 108 : : } 109 : : #else 110 : 0 : bool DdsCdrPubSubType::serialize(void* data, rtps::SerializedPayload_t* payload) { 111 [ # # # # ]: 0 : return payload != nullptr && copy_to_payload(*static_cast<const Bytes*>(data), *payload); 112 : : } 113 : : 114 : 0 : bool DdsCdrPubSubType::deserialize(rtps::SerializedPayload_t* payload, void* data) { 115 [ # # # # ]: 0 : return payload != nullptr && copy_from_payload(*payload, *static_cast<Bytes*>(data)); 116 : : } 117 : : 118 : 0 : std::function<uint32_t()> DdsCdrPubSubType::getSerializedSizeProvider(void* data) { 119 : 0 : return [data] { 120 : 0 : const auto size = static_cast<Bytes*>(data)->size(); 121 [ # # ]: 0 : return size <= std::numeric_limits<uint32_t>::max() ? static_cast<uint32_t>(size) : 0U; 122 : 0 : }; 123 : : } 124 : : 125 : 0 : bool DdsCdrPubSubType::getKey(void* data, rtps::InstanceHandle_t* handle, bool force_md5) { 126 [ # # # # : 0 : if VUNLIKELY (!native_type_ || !handle) { # # ] 127 : 0 : return false; 128 : : } 129 : : 130 : 0 : rtps::SerializedPayload_t payload; 131 : : 132 [ # # # # ]: 0 : if VUNLIKELY (!copy_to_payload(*static_cast<Bytes*>(data), payload)) { 133 : 0 : return false; 134 : : } 135 : : 136 [ # # ]: 0 : void* sample = native_type_.create_data(); 137 [ # # # # : 0 : const bool result = sample != nullptr && native_type_->deserialize(&payload, sample) && # # ] 138 [ # # # # ]: 0 : native_type_->getKey(sample, handle, force_md5); 139 : : 140 [ # # ]: 0 : if VUNLIKELY (sample) { 141 [ # # ]: 0 : native_type_.delete_data(sample); 142 : : } 143 : : 144 : 0 : return result; 145 : 0 : } 146 : : 147 : 0 : void* DdsCdrPubSubType::createData() { return new Bytes; } 148 : : 149 [ # # ]: 0 : void DdsCdrPubSubType::deleteData(void* data) { delete static_cast<Bytes*>(data); } 150 : : #endif 151 : : 152 : 0 : bool DdsCdrPubSubType::copy_to_payload(const Bytes& bytes, rtps::SerializedPayload_t& payload) { 153 [ # # # # : 0 : if VUNLIKELY (!bytes.data() || bytes.size() < 4U || bytes.size() > std::numeric_limits<uint32_t>::max()) { # # # # # # ] 154 : 0 : return false; 155 : : } 156 : : 157 : 0 : const auto size = static_cast<uint32_t>(bytes.size()); 158 : : 159 [ # # ]: 0 : if VUNLIKELY (payload.max_size < size) { 160 : : try { 161 [ # # ]: 0 : payload.reserve(size); 162 [ - - ]: 0 : } catch (const std::bad_alloc&) { 163 : 0 : return false; 164 : 0 : } 165 : : } 166 [ # # # # : 0 : if VUNLIKELY (!payload.data || payload.max_size < size) { # # ] 167 : 0 : return false; 168 : : } 169 : : 170 : 0 : std::memcpy(payload.data, bytes.data(), size); 171 : 0 : payload.length = size; 172 : 0 : payload.encapsulation = static_cast<uint16_t>((static_cast<uint16_t>(bytes.data()[0]) << 8U) | bytes.data()[1]); 173 : : 174 : 0 : return true; 175 : : } 176 : : 177 : 0 : bool DdsCdrPubSubType::copy_from_payload(const rtps::SerializedPayload_t& payload, Bytes& bytes) { 178 [ # # # # : 0 : if VUNLIKELY (!payload.data || payload.length < 4U) { # # ] 179 : 0 : return false; 180 : : } 181 : : 182 : 0 : bytes = Bytes::shallow_copy(payload.data, payload.length); 183 : : 184 : 0 : return true; 185 : : } 186 : : 187 : : } // namespace vlink