• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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