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