protocol_core.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef CRDTP_PROTOCOL_CORE_H_
  5. #define CRDTP_PROTOCOL_CORE_H_
  6. #include <sys/types.h>
  7. #include <memory>
  8. #include <string>
  9. #include <vector>
  10. #include "cbor.h"
  11. #include "maybe.h"
  12. #include "serializable.h"
  13. #include "span.h"
  14. #include "status.h"
  15. namespace crdtp {
  16. class CRDTP_EXPORT DeserializerState {
  17. public:
  18. using Storage = std::shared_ptr<const std::vector<uint8_t>>;
  19. // Creates a state from the raw bytes received from the peer.
  20. explicit DeserializerState(std::vector<uint8_t> bytes);
  21. // Creates the state from the part of another message.
  22. DeserializerState(Storage storage, span<uint8_t> span);
  23. DeserializerState(const DeserializerState& r) = delete;
  24. DeserializerState(DeserializerState&& r) = default;
  25. // Registers |error|, unless the tokenizer's status is already an error.
  26. void RegisterError(Error error);
  27. // Registers |name| as a segment of the field path.
  28. void RegisterFieldPath(span<char> name);
  29. // Produces an error message considering |tokenizer.Status()|,
  30. // status_, and field_path_.
  31. std::string ErrorMessage(span<char> message_name) const;
  32. Status status() const;
  33. const Storage& storage() const { return storage_; }
  34. cbor::CBORTokenizer* tokenizer() { return &tokenizer_; }
  35. private:
  36. const Storage storage_;
  37. cbor::CBORTokenizer tokenizer_;
  38. Status status_;
  39. std::vector<span<char>> field_path_;
  40. };
  41. template <typename T, typename = void>
  42. struct ProtocolTypeTraits {};
  43. template <>
  44. struct CRDTP_EXPORT ProtocolTypeTraits<bool> {
  45. static bool Deserialize(DeserializerState* state, bool* value);
  46. static void Serialize(bool value, std::vector<uint8_t>* bytes);
  47. };
  48. template <>
  49. struct CRDTP_EXPORT ProtocolTypeTraits<int32_t> {
  50. static bool Deserialize(DeserializerState* state, int* value);
  51. static void Serialize(int value, std::vector<uint8_t>* bytes);
  52. };
  53. template <>
  54. struct CRDTP_EXPORT ProtocolTypeTraits<double> {
  55. static bool Deserialize(DeserializerState* state, double* value);
  56. static void Serialize(double value, std::vector<uint8_t>* bytes);
  57. };
  58. class CRDTP_EXPORT ContainerSerializer {
  59. public:
  60. ContainerSerializer(std::vector<uint8_t>* bytes, uint8_t tag);
  61. template <typename T>
  62. void AddField(span<char> field_name, const T& value) {
  63. cbor::EncodeString8(
  64. span<uint8_t>(reinterpret_cast<const uint8_t*>(field_name.data()),
  65. field_name.size()),
  66. bytes_);
  67. ProtocolTypeTraits<T>::Serialize(value, bytes_);
  68. }
  69. template <typename T>
  70. void AddField(span<char> field_name, const detail::ValueMaybe<T>& value) {
  71. if (!value.isJust())
  72. return;
  73. AddField(field_name, value.fromJust());
  74. }
  75. template <typename T>
  76. void AddField(span<char> field_name, const detail::PtrMaybe<T>& value) {
  77. if (!value.isJust())
  78. return;
  79. AddField(field_name, *value.fromJust());
  80. }
  81. void EncodeStop();
  82. private:
  83. std::vector<uint8_t>* const bytes_;
  84. cbor::EnvelopeEncoder envelope_;
  85. };
  86. class CRDTP_EXPORT ObjectSerializer {
  87. public:
  88. ObjectSerializer();
  89. ~ObjectSerializer();
  90. template <typename T>
  91. void AddField(span<char> name, const T& field) {
  92. serializer_.AddField(name, field);
  93. }
  94. std::unique_ptr<Serializable> Finish();
  95. private:
  96. std::vector<uint8_t> owned_bytes_;
  97. ContainerSerializer serializer_;
  98. };
  99. class CRDTP_EXPORT DeserializerDescriptor {
  100. public:
  101. struct CRDTP_EXPORT Field {
  102. span<char> name;
  103. bool is_optional;
  104. bool (*deserializer)(DeserializerState* state, void* obj);
  105. };
  106. DeserializerDescriptor(const Field* fields, size_t field_count);
  107. bool Deserialize(DeserializerState* state, void* obj) const;
  108. private:
  109. bool DeserializeField(DeserializerState* state,
  110. span<char> name,
  111. int* seen_mandatory_fields,
  112. void* obj) const;
  113. const Field* const fields_;
  114. const size_t field_count_;
  115. const int mandatory_field_mask_;
  116. };
  117. template <typename T>
  118. struct ProtocolTypeTraits<std::vector<T>> {
  119. static bool Deserialize(DeserializerState* state, std::vector<T>* value) {
  120. auto* tokenizer = state->tokenizer();
  121. if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE)
  122. tokenizer->EnterEnvelope();
  123. if (tokenizer->TokenTag() != cbor::CBORTokenTag::ARRAY_START) {
  124. state->RegisterError(Error::CBOR_ARRAY_START_EXPECTED);
  125. return false;
  126. }
  127. assert(value->empty());
  128. tokenizer->Next();
  129. for (; tokenizer->TokenTag() != cbor::CBORTokenTag::STOP;
  130. tokenizer->Next()) {
  131. value->emplace_back();
  132. if (!ProtocolTypeTraits<T>::Deserialize(state, &value->back()))
  133. return false;
  134. }
  135. return true;
  136. }
  137. static void Serialize(const std::vector<T>& value,
  138. std::vector<uint8_t>* bytes) {
  139. ContainerSerializer container_serializer(
  140. bytes, cbor::EncodeIndefiniteLengthArrayStart());
  141. for (const auto& item : value)
  142. ProtocolTypeTraits<T>::Serialize(item, bytes);
  143. container_serializer.EncodeStop();
  144. }
  145. };
  146. template <typename T>
  147. struct ProtocolTypeTraits<std::unique_ptr<std::vector<T>>> {
  148. static bool Deserialize(DeserializerState* state,
  149. std::unique_ptr<std::vector<T>>* value) {
  150. auto res = std::make_unique<std::vector<T>>();
  151. if (!ProtocolTypeTraits<std::vector<T>>::Deserialize(state, res.get()))
  152. return false;
  153. *value = std::move(res);
  154. return true;
  155. }
  156. static void Serialize(const std::unique_ptr<std::vector<T>>& value,
  157. std::vector<uint8_t>* bytes) {
  158. ProtocolTypeTraits<std::vector<T>>::Serialize(*value, bytes);
  159. }
  160. };
  161. class CRDTP_EXPORT DeferredMessage : public Serializable {
  162. public:
  163. static std::unique_ptr<DeferredMessage> FromSerializable(
  164. std::unique_ptr<Serializable> serializeable);
  165. static std::unique_ptr<DeferredMessage> FromSpan(span<uint8_t> bytes);
  166. ~DeferredMessage() override = default;
  167. virtual DeserializerState MakeDeserializer() const = 0;
  168. protected:
  169. DeferredMessage() = default;
  170. };
  171. template <>
  172. struct CRDTP_EXPORT ProtocolTypeTraits<std::unique_ptr<DeferredMessage>> {
  173. static bool Deserialize(DeserializerState* state,
  174. std::unique_ptr<DeferredMessage>* value);
  175. static void Serialize(const std::unique_ptr<DeferredMessage>& value,
  176. std::vector<uint8_t>* bytes);
  177. };
  178. template <typename T>
  179. struct ProtocolTypeTraits<detail::ValueMaybe<T>> {
  180. static bool Deserialize(DeserializerState* state,
  181. detail::ValueMaybe<T>* value) {
  182. T res;
  183. if (!ProtocolTypeTraits<T>::Deserialize(state, &res))
  184. return false;
  185. *value = std::move(res);
  186. return true;
  187. }
  188. static void Serialize(const detail::ValueMaybe<T>& value,
  189. std::vector<uint8_t>* bytes) {
  190. ProtocolTypeTraits<T>::Serialize(value.fromJust(), bytes);
  191. }
  192. };
  193. template <typename T>
  194. struct ProtocolTypeTraits<detail::PtrMaybe<T>> {
  195. static bool Deserialize(DeserializerState* state,
  196. detail::PtrMaybe<T>* value) {
  197. std::unique_ptr<T> res;
  198. if (!ProtocolTypeTraits<std::unique_ptr<T>>::Deserialize(state, &res))
  199. return false;
  200. *value = std::move(res);
  201. return true;
  202. }
  203. static void Serialize(const detail::PtrMaybe<T>& value,
  204. std::vector<uint8_t>* bytes) {
  205. ProtocolTypeTraits<T>::Serialize(*value.fromJust(), bytes);
  206. }
  207. };
  208. template <typename T>
  209. class DeserializableProtocolObject {
  210. public:
  211. static StatusOr<std::unique_ptr<T>> ReadFrom(
  212. const DeferredMessage& deferred_message) {
  213. auto state = deferred_message.MakeDeserializer();
  214. if (auto res = Deserialize(&state))
  215. return StatusOr<std::unique_ptr<T>>(std::move(res));
  216. return StatusOr<std::unique_ptr<T>>(state.status());
  217. }
  218. static StatusOr<std::unique_ptr<T>> ReadFrom(std::vector<uint8_t> bytes) {
  219. auto state = DeserializerState(std::move(bytes));
  220. if (auto res = Deserialize(&state))
  221. return StatusOr<std::unique_ptr<T>>(std::move(res));
  222. return StatusOr<std::unique_ptr<T>>(state.status());
  223. }
  224. // Short-hand for legacy clients. This would swallow any errors, consider
  225. // using ReadFrom.
  226. static std::unique_ptr<T> FromBinary(const uint8_t* bytes, size_t size) {
  227. std::unique_ptr<T> value(new T());
  228. auto deserializer = DeferredMessage::FromSpan(span<uint8_t>(bytes, size))
  229. ->MakeDeserializer();
  230. std::ignore = Deserialize(&deserializer, value.get());
  231. return value;
  232. }
  233. [[nodiscard]] static bool Deserialize(DeserializerState* state, T* value) {
  234. return T::deserializer_descriptor().Deserialize(state, value);
  235. }
  236. protected:
  237. // This is for the sake of the macros used by derived classes thay may be in
  238. // a different namespace;
  239. using ProtocolType = T;
  240. using DeserializerDescriptorType = DeserializerDescriptor;
  241. template <typename U>
  242. using DeserializableBase = DeserializableProtocolObject<U>;
  243. DeserializableProtocolObject() = default;
  244. ~DeserializableProtocolObject() = default;
  245. private:
  246. friend struct ProtocolTypeTraits<std::unique_ptr<T>>;
  247. static std::unique_ptr<T> Deserialize(DeserializerState* state) {
  248. std::unique_ptr<T> value(new T());
  249. if (Deserialize(state, value.get()))
  250. return value;
  251. return nullptr;
  252. }
  253. };
  254. template <typename T>
  255. class ProtocolObject : public Serializable,
  256. public DeserializableProtocolObject<T> {
  257. public:
  258. std::unique_ptr<T> Clone() const {
  259. std::vector<uint8_t> serialized;
  260. AppendSerialized(&serialized);
  261. return T::ReadFrom(std::move(serialized)).value();
  262. }
  263. // TODO(caseq): compatibility only, remove.
  264. std::unique_ptr<T> clone() const { return Clone(); }
  265. protected:
  266. using ProtocolType = T;
  267. ProtocolObject() = default;
  268. };
  269. template <typename T>
  270. struct ProtocolTypeTraits<
  271. T,
  272. typename std::enable_if<
  273. std::is_base_of<ProtocolObject<T>, T>::value>::type> {
  274. static bool Deserialize(DeserializerState* state, T* value) {
  275. return T::Deserialize(state, value);
  276. }
  277. static void Serialize(const T& value, std::vector<uint8_t>* bytes) {
  278. value.AppendSerialized(bytes);
  279. }
  280. };
  281. template <typename T>
  282. struct ProtocolTypeTraits<
  283. std::unique_ptr<T>,
  284. typename std::enable_if<
  285. std::is_base_of<ProtocolObject<T>, T>::value>::type> {
  286. static bool Deserialize(DeserializerState* state, std::unique_ptr<T>* value) {
  287. std::unique_ptr<T> res = T::Deserialize(state);
  288. if (!res)
  289. return false;
  290. *value = std::move(res);
  291. return true;
  292. }
  293. static void Serialize(const std::unique_ptr<T>& value,
  294. std::vector<uint8_t>* bytes) {
  295. ProtocolTypeTraits<T>::Serialize(*value, bytes);
  296. }
  297. };
  298. template <typename T, typename F>
  299. bool ConvertProtocolValue(const F& from, T* to) {
  300. std::vector<uint8_t> bytes;
  301. ProtocolTypeTraits<F>::Serialize(from, &bytes);
  302. auto deserializer =
  303. DeferredMessage::FromSpan(span<uint8_t>(bytes.data(), bytes.size()))
  304. ->MakeDeserializer();
  305. return ProtocolTypeTraits<T>::Deserialize(&deserializer, to);
  306. }
  307. #define DECLARE_DESERIALIZATION_SUPPORT() \
  308. friend DeserializableBase<ProtocolType>; \
  309. static const DeserializerDescriptorType& deserializer_descriptor()
  310. #define DECLARE_SERIALIZATION_SUPPORT() \
  311. public: \
  312. void AppendSerialized(std::vector<uint8_t>* bytes) const override; \
  313. \
  314. private: \
  315. friend DeserializableBase<ProtocolType>; \
  316. static const DeserializerDescriptorType& deserializer_descriptor()
  317. #define CRDTP_DESERIALIZE_FILED_IMPL(name, field, is_optional) \
  318. { \
  319. MakeSpan(name), is_optional, \
  320. [](DeserializerState* __state, void* __obj) -> bool { \
  321. return ProtocolTypeTraits<decltype(field)>::Deserialize( \
  322. __state, &static_cast<ProtocolType*>(__obj)->field); \
  323. } \
  324. }
  325. // clang-format off
  326. #define CRDTP_BEGIN_DESERIALIZER(type) \
  327. const type::DeserializerDescriptorType& type::deserializer_descriptor() { \
  328. using namespace crdtp; \
  329. static const DeserializerDescriptorType::Field fields[] = {
  330. #define CRDTP_END_DESERIALIZER() \
  331. }; \
  332. static const DeserializerDescriptorType s_desc( \
  333. fields, sizeof fields / sizeof fields[0]); \
  334. return s_desc; \
  335. }
  336. #define CRDTP_DESERIALIZE_FIELD(name, field) \
  337. CRDTP_DESERIALIZE_FILED_IMPL(name, field, false)
  338. #define CRDTP_DESERIALIZE_FIELD_OPT(name, field) \
  339. CRDTP_DESERIALIZE_FILED_IMPL(name, field, true)
  340. #define CRDTP_BEGIN_SERIALIZER(type) \
  341. void type::AppendSerialized(std::vector<uint8_t>* bytes) const { \
  342. using namespace crdtp; \
  343. ContainerSerializer __serializer(bytes, \
  344. cbor::EncodeIndefiniteLengthMapStart());
  345. #define CRDTP_SERIALIZE_FIELD(name, field) \
  346. __serializer.AddField(MakeSpan(name), field)
  347. #define CRDTP_END_SERIALIZER() \
  348. __serializer.EncodeStop(); \
  349. } class __cddtp_dummy_name
  350. // clang-format on
  351. } // namespace crdtp
  352. #endif // CRDTP_PROTOCOL_CORE_H_