CARLA
 
载入中...
搜索中...
未找到
MsgPackAdaptors.h
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#pragma once
8
9#include "carla/Exception.h"//包含 Carla 项目中定义的异常类的头文件
10#include "carla/MsgPack.h"//包含 Carla 项目中用于消息打包(可能是序列化)的头文件
11
12#include <boost/optional.hpp>//包含 Boost.Optional 库的头文件
13
14#ifdef _MSC_VER//这是一个条件编译指令,用于检查是否定义了宏 _MSC_VER
15#pragma warning(push)//将当前的警告设置保存到一个堆栈中
16#pragma warning(disable:4583)
17#pragma warning(disable:4582)
18#include <boost/variant2/variant.hpp>//包含 Boost.Variant2 库的头文件
19#pragma warning(pop)//恢复之前保存的警告设置
20#else
21#include <boost/variant2/variant.hpp>
22#endif
23
24#include <tuple>
25
26namespace clmdep_msgpack {
27MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
28namespace adaptor {
29
30 // ===========================================================================
31 // -- Adaptors for boost::optional -------------------------------------------
32 // ===========================================================================
33
34 // 为 boost::optional<T> 定义的转换特化
35 template<typename T>
36 struct convert<boost::optional<T>> {
37
38 // 重载函数调用运算符,将 MsgPack 对象转换为 boost::optional<T>
39 const clmdep_msgpack::object &operator()(
40 const clmdep_msgpack::object &o,
41 boost::optional<T> &v) const {
42 // 确保 MsgPack 对象是一个数组
43 if (o.type != clmdep_msgpack::type::ARRAY) {
44 ::carla::throw_exception(clmdep_msgpack::type_error());
45 }
46
47 // 检查数组大小以决定如何设置 optional
48 if (o.via.array.size == 1) {
49 // 如果大小为 1,表示没有值
50 v.reset();
51 } else if (o.via.array.size == 2) {
52 // 如果大小为 2,从第二个元素中获取值
53 v.reset(o.via.array.ptr[1].as<T>());
54 } else {
55 // 如果大小不为 1 或 2,抛出类型错误
56 ::carla::throw_exception(clmdep_msgpack::type_error());
57 }
58 return o;
59 }
60 };
61 // 为 boost::optional<T> 定义的打包特化
62 template<typename T>
63 struct pack<boost::optional<T>> {
64 template <typename Stream>
65 packer<Stream> &operator()(
66 clmdep_msgpack::packer<Stream> &o,
67 const boost::optional<T> &v) const {
68 if (v.has_value()) {
69 // 如果 optional 有值,将其打包为大小为 2 的数组
70 o.pack_array(2);
71 o.pack(true);// 第一个元素表示存在
72 o.pack(*v);// 第二个元素是实际值
73 } else {
74 // 如果 optional 为空,将其打包为大小为 1 的数组
75 o.pack_array(1);
76 o.pack(false);// 表示值不存在
77 }
78 return o;
79 }
80 };
81 // 为 boost::optional<T> 定义的带区域的对象特化
82 template<typename T>
83 struct object_with_zone<boost::optional<T>> {
84 void operator()(
85 clmdep_msgpack::object::with_zone &o,
86 const boost::optional<T> &v) const {
87 o.type = type::ARRAY; // 设置类型为数组
88 if (v.has_value()) {
89 // 如果 optional 有值,设置大小为 2 并分配内存
90 o.via.array.size = 2;
91 o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
92 sizeof(clmdep_msgpack::object) * o.via.array.size,
93 MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
94 // 第一个元素:true(表示存在)
95 o.via.array.ptr[0] = clmdep_msgpack::object(true, o.zone);
96 // 第二个元素:实际值
97 o.via.array.ptr[1] = clmdep_msgpack::object(*v, o.zone);
98 } else {
99 // 如果 optional 为空,设置大小为 1 并分配内存
100 o.via.array.size = 1;
101 o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
102 sizeof(clmdep_msgpack::object) * o.via.array.size,
103 MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
104 // 第一个元素:false(表示不存在)
105 o.via.array.ptr[0] = clmdep_msgpack::object(false, o.zone);
106 }
107 }
108 };
109
110 // ===========================================================================
111 // -- Adaptors for boost::variant2::variant ----------------------------------
112 // ===========================================================================
113
114 template<typename... Ts>
115 struct convert<boost::variant2::variant<Ts...>> {
116
117 const clmdep_msgpack::object &operator()(
118 const clmdep_msgpack::object &o,
119 boost::variant2::variant<Ts...> &v) const {
120 // 检查对象类型是否为数组
121 if (o.type != clmdep_msgpack::type::ARRAY) {
122 ::carla::throw_exception(clmdep_msgpack::type_error());
123 }
124 // 检查数组大小是否为 2
125 if (o.via.array.size != 2) {
126 ::carla::throw_exception(clmdep_msgpack::type_error());
127 }
128 // 获取索引
129 const auto index = o.via.array.ptr[0].as<uint64_t>();
130 copy_to_variant(index, o, v, std::make_index_sequence<sizeof...(Ts)>());
131 return o;
132 }
133
134 private:
135
136 // 从对象中复制到变体的实现
137 template <uint64_t I>
138 static void copy_to_variant_impl(
139 const clmdep_msgpack::object &o,
140 boost::variant2::variant<Ts...> &v) {
141 /// @todo 找到类型的工作环绕。
142 auto dummy = std::get<I>(std::tuple<Ts...>{});
143 using T = decltype(dummy);
144 v = o.via.array.ptr[1].as<T>();// 从对象中获取并赋值给变体
145 }
146 // 复制到变体的主函数
147 template <uint64_t... Is>
148// 函数名为 `copy_to_variant`,它是一个静态成员函数,意味着可以通过类名直接调用,而不需要实例化类对象
149// 该函数的作用从参数来看可能是将某个 `clmdep_msgpack::object` 类型的数据根据索引复制到 `boost::variant2::variant<Ts...>` 类型的变量中
150// 这里的 `Ts...` 同样是可变参数模板参数,代表一系列的类型(具体由调用时传入的类型决定)
151 static void copy_to_variant(
152// `index` 参数,类型为 `uint64_t`,可能用于指定要操作的索引位置,用于在下面的逻辑中判断和选择合适的处理分支
153 const uint64_t index,
154// `o` 参数,类型为 `clmdep_msgpack::object`,应该是要被复制的数据来源对象
155 const clmdep_msgpack::object &o,
156// `v` 参数,类型为 `boost::variant2::variant<Ts...>`,是目标变量,也就是要将数据复制到其中的变量
157 boost::variant2::variant<Ts...> &v,
158// `std::index_sequence<Is...>` 是一个编译期的索引序列,用于辅助实现一些编译期的循环或者按索引展开等操作(常配合可变参数模板使用)
159 std::index_sequence<Is...>) {
160 // 使用初始化列表语法,初始化列表中的元素表达式通过逗号分隔
161 // 这里的表达式 `(index == Is? copy_to_variant_impl<Is>(o, v), 0 : 0)...` 是一个展开式,会针对每个 `Is` 值进行展开
162 // 意思是如果当前的 `index` 值等于某个 `Is` 值,就调用 `copy_to_variant_impl<Is>(o, v)` 函数(具体功能由该函数定义决定,这里应该是真正执行复制数据到变体类型变量 `v` 的操作),并且整个表达式返回值为 `0`(这里的 `0` 只是为了满足初始化列表元素语法要求,并无实际业务含义);如果 `index` 不等于 `Is`,就直接返回 `0`
163 std::initializer_list<int> ({
164 (index == Is ? copy_to_variant_impl<Is>(o, v), 0 : 0)...
165 });
166 }
167 };
168// 定义一个模板结构体 `pack`,针对 `boost::variant2::variant<Ts...>` 类型进行特化(这里 `Ts...` 同样是可变参数模板参数,表示一系列类型)
169// 这个结构体可能用于对 `boost::variant2::variant` 类型进行一些打包或者序列化相关的操作(结合后面的函数重载推测)
170 template<typename... Ts>
171 struct pack<boost::variant2::variant<Ts...>> {
172 // 定义一个函数重载操作符 `()`,使得该结构体的对象可以像函数一样被调用
173 // 这个函数接受一个 `clmdep_msgpack::packer<Stream>` 类型的引用 `o`(从类型来看可能是用于将数据打包到某个流中的工具类对象),以及一个 `const boost::variant2::variant<Ts...> &` 类型的常量引用 `v`(要被打包的数据,也就是上面提到的变体类型变量)
174 template <typename Stream>
175 packer<Stream> &operator()(
176 clmdep_msgpack::packer<Stream> &o,
177 const boost::variant2::variant<Ts...> &v) const {
178 o.pack_array(2);// 打包数组大小
179 o.pack(static_cast<uint64_t>(v.index()));
180 // 使用访问器打包变体的值
181 boost::variant2::visit([&](const auto &value) { o.pack(value); }, v);
182 return o;
183 }
184 };
185// 定义一个模板结构体 `object_with_zone`,针对 `boost::variant2::variant<Ts...>` 类型进行特化。
186// 这里的 `Ts...` 是可变参数模板参数,表示一系列的类型,意味着这个结构体针对 `boost::variant2::variant` 包含不同具体类型的情况做特殊处理。
187 template<typename... Ts>
188 struct object_with_zone<boost::variant2::variant<Ts...>> {
189 // 定义函数调用操作符 `()`,使得该结构体的对象可以像函数一样被调用,这里的函数是 `const`(常量)成员函数,意味着它不会修改对象的成员变量(如果有的话)。
190 // 函数接受两个参数,第一个参数 `o` 是 `clmdep_msgpack::object::with_zone` 类型的引用,从名字推测可能是与带区域(zone,也许和内存分配区域等概念相关)的消息包对象相关,第二个参数 `v` 是 `const boost::variant2::variant<Ts...> &` 类型的常量引用,即要操作的变体类型的数据
191 void operator()(
192 clmdep_msgpack::object::with_zone &o,
193 const boost::variant2::variant<Ts...> &v) const {
194// 将传入的 `clmdep_msgpack::object::with_zone` 类型对象 `o` 的 `type` 成员变量设置为 `type::ARRAY`,表明接下来要处理的数据结构形式可能是数组形式(这里的 `type` 应该是用于标记对象的数据类型相关属性,具体取决于 `clmdep_msgpack::object` 类型的定义)。
195 o.type = type::ARRAY;
196// 设置 `o` 对象中与数组相关的成员变量 `size`,将其赋值为 `2`,意味着接下来要处理的这个数组结构可能包含两个元素(具体含义需结合更多该类型相关的逻辑来确定)。
197 o.via.array.size = 2;
198// 调用 `o` 对象所属区域(zone)的 `allocate_align` 函数,为存储 `clmdep_msgpack::object` 类型的数据分配内存空间
199// `sizeof(clmdep_msgpack::object) * o.via.array.size` 计算出需要分配的内存大小,是 `clmdep_msgpack::object` 类型的大小乘以数组元素个数(这里前面设置为 `2`)。
200 // `MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)` 可能是用于指定内存对齐方式相关的参数,确保分配的内存按照合适的对齐要求来进行,便于后续对数据的高效访问等操作。
201 // 然后将分配得到的内存地址转换为 `clmdep_msgpack::object*` 类型(即指向 `clmdep_msgpack::object` 类型对象的指针),并赋值给 `o` 对象中与数组相关的 `ptr` 成员变量,这样 `o` 对象就能通过这个指针来访问分配好的内存空间用于存储数组元素了。
202 o.via.array.ptr = static_cast<clmdep_msgpack::object*>(o.zone.allocate_align(
203 sizeof(clmdep_msgpack::object) * o.via.array.size,
204 MSGPACK_ZONE_ALIGNOF(clmdep_msgpack::object)));
205 // 设置数组的第一个元素为索引
206 o.via.array.ptr[0] = clmdep_msgpack::object(static_cast<uint64_t>(v.index()), o.zone);
207 boost::variant2::visit([&](const auto &value) {
208 o.via.array.ptr[1] = clmdep_msgpack::object(value, o.zone);
209 }, v);
210 }
211 };
212
213} // namespace adaptor
214} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
215} // namespace msgpack
void throw_exception(const std::exception &e)
Definition Carla.cpp:142
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)