• 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 #include "protocol_core.h"
6 
7 #include <algorithm>
8 #include <cassert>
9 #include <string>
10 
11 namespace v8_crdtp {
12 
DeserializerState(std::vector<uint8_t> bytes)13 DeserializerState::DeserializerState(std::vector<uint8_t> bytes)
14     : storage_(new std::vector<uint8_t>(std::move(bytes))),
15       tokenizer_(span<uint8_t>(storage_->data(), storage_->size())) {}
16 
DeserializerState(Storage storage,span<uint8_t> span)17 DeserializerState::DeserializerState(Storage storage, span<uint8_t> span)
18     : storage_(std::move(storage)), tokenizer_(span) {}
19 
RegisterError(Error error)20 void DeserializerState::RegisterError(Error error) {
21   assert(Error::OK != error);
22   if (tokenizer_.Status().ok())
23     status_ = Status{error, tokenizer_.Status().pos};
24 }
25 
RegisterFieldPath(span<char> name)26 void DeserializerState::RegisterFieldPath(span<char> name) {
27   field_path_.push_back(name);
28 }
29 
ErrorMessage(span<char> message_name) const30 std::string DeserializerState::ErrorMessage(span<char> message_name) const {
31   std::string msg = "Failed to deserialize ";
32   msg.append(message_name.begin(), message_name.end());
33   for (int field = static_cast<int>(field_path_.size()) - 1; field >= 0;
34        --field) {
35     msg.append(".");
36     msg.append(field_path_[field].begin(), field_path_[field].end());
37   }
38   Status s = status();
39   if (!s.ok())
40     msg += " - " + s.ToASCIIString();
41   return msg;
42 }
43 
status() const44 Status DeserializerState::status() const {
45   if (!tokenizer_.Status().ok())
46     return tokenizer_.Status();
47   return status_;
48 }
49 
50 namespace {
GetMandatoryFieldMask(const DeserializerDescriptor::Field * fields,size_t count)51 constexpr int32_t GetMandatoryFieldMask(
52     const DeserializerDescriptor::Field* fields,
53     size_t count) {
54   int32_t mask = 0;
55   for (size_t i = 0; i < count; ++i) {
56     if (!fields[i].is_optional)
57       mask |= (1 << i);
58   }
59   return mask;
60 }
61 }  // namespace
62 
DeserializerDescriptor(const Field * fields,size_t field_count)63 DeserializerDescriptor::DeserializerDescriptor(const Field* fields,
64                                                size_t field_count)
65     : fields_(fields),
66       field_count_(field_count),
67       mandatory_field_mask_(GetMandatoryFieldMask(fields, field_count)) {}
68 
Deserialize(DeserializerState * state,void * obj) const69 bool DeserializerDescriptor::Deserialize(DeserializerState* state,
70                                          void* obj) const {
71   auto* tokenizer = state->tokenizer();
72 
73   // As a special compatibility quirk, allow empty objects if
74   // no mandatory fields are required.
75   if (tokenizer->TokenTag() == cbor::CBORTokenTag::DONE &&
76       !mandatory_field_mask_) {
77     return true;
78   }
79   if (tokenizer->TokenTag() == cbor::CBORTokenTag::ENVELOPE)
80     tokenizer->EnterEnvelope();
81   if (tokenizer->TokenTag() != cbor::CBORTokenTag::MAP_START) {
82     state->RegisterError(Error::CBOR_MAP_START_EXPECTED);
83     return false;
84   }
85   tokenizer->Next();
86   int32_t seen_mandatory_fields = 0;
87   for (; tokenizer->TokenTag() != cbor::CBORTokenTag::STOP; tokenizer->Next()) {
88     if (tokenizer->TokenTag() != cbor::CBORTokenTag::STRING8) {
89       state->RegisterError(Error::CBOR_INVALID_MAP_KEY);
90       return false;
91     }
92     span<uint8_t> u_key = tokenizer->GetString8();
93     span<char> key(reinterpret_cast<const char*>(u_key.data()), u_key.size());
94     tokenizer->Next();
95     if (!DeserializeField(state, key, &seen_mandatory_fields, obj))
96       return false;
97   }
98   // Only compute mandatory fields once per type.
99   int32_t missing_fields = seen_mandatory_fields ^ mandatory_field_mask_;
100   if (missing_fields) {
101     int32_t idx = 0;
102     while ((missing_fields & 1) == 0) {
103       missing_fields >>= 1;
104       ++idx;
105     }
106     state->RegisterError(Error::BINDINGS_MANDATORY_FIELD_MISSING);
107     state->RegisterFieldPath(fields_[idx].name);
108     return false;
109   }
110   return true;
111 }
112 
DeserializeField(DeserializerState * state,span<char> name,int * seen_mandatory_fields,void * obj) const113 bool DeserializerDescriptor::DeserializeField(DeserializerState* state,
114                                               span<char> name,
115                                               int* seen_mandatory_fields,
116                                               void* obj) const {
117   // TODO(caseq): consider checking if the sought field is the one
118   // after the last deserialized.
119   const auto* begin = fields_;
120   const auto* end = fields_ + field_count_;
121   auto entry = std::lower_bound(
122       begin, end, name, [](const Field& field_desc, span<char> field_name) {
123         return SpanLessThan(field_desc.name, field_name);
124       });
125   // Unknown field is not an error -- we may be working against an
126   // implementation of a later version of the protocol.
127   // TODO(caseq): support unknown arrays and maps not enclosed by an envelope.
128   if (entry == end || !SpanEquals(entry->name, name))
129     return true;
130   if (!entry->deserializer(state, obj)) {
131     state->RegisterFieldPath(name);
132     return false;
133   }
134   if (!entry->is_optional)
135     *seen_mandatory_fields |= 1 << (entry - begin);
136   return true;
137 }
138 
Deserialize(DeserializerState * state,bool * value)139 bool ProtocolTypeTraits<bool>::Deserialize(DeserializerState* state,
140                                            bool* value) {
141   const auto tag = state->tokenizer()->TokenTag();
142   if (tag == cbor::CBORTokenTag::TRUE_VALUE) {
143     *value = true;
144     return true;
145   }
146   if (tag == cbor::CBORTokenTag::FALSE_VALUE) {
147     *value = false;
148     return true;
149   }
150   state->RegisterError(Error::BINDINGS_BOOL_VALUE_EXPECTED);
151   return false;
152 }
153 
Serialize(bool value,std::vector<uint8_t> * bytes)154 void ProtocolTypeTraits<bool>::Serialize(bool value,
155                                          std::vector<uint8_t>* bytes) {
156   bytes->push_back(value ? cbor::EncodeTrue() : cbor::EncodeFalse());
157 }
158 
Deserialize(DeserializerState * state,int32_t * value)159 bool ProtocolTypeTraits<int32_t>::Deserialize(DeserializerState* state,
160                                               int32_t* value) {
161   if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::INT32) {
162     state->RegisterError(Error::BINDINGS_INT32_VALUE_EXPECTED);
163     return false;
164   }
165   *value = state->tokenizer()->GetInt32();
166   return true;
167 }
168 
Serialize(int32_t value,std::vector<uint8_t> * bytes)169 void ProtocolTypeTraits<int32_t>::Serialize(int32_t value,
170                                             std::vector<uint8_t>* bytes) {
171   cbor::EncodeInt32(value, bytes);
172 }
173 
ContainerSerializer(std::vector<uint8_t> * bytes,uint8_t tag)174 ContainerSerializer::ContainerSerializer(std::vector<uint8_t>* bytes,
175                                          uint8_t tag)
176     : bytes_(bytes) {
177   envelope_.EncodeStart(bytes_);
178   bytes_->push_back(tag);
179 }
180 
EncodeStop()181 void ContainerSerializer::EncodeStop() {
182   bytes_->push_back(cbor::EncodeStop());
183   envelope_.EncodeStop(bytes_);
184 }
185 
ObjectSerializer()186 ObjectSerializer::ObjectSerializer()
187     : serializer_(&owned_bytes_, cbor::EncodeIndefiniteLengthMapStart()) {}
188 
189 ObjectSerializer::~ObjectSerializer() = default;
190 
Finish()191 std::unique_ptr<Serializable> ObjectSerializer::Finish() {
192   serializer_.EncodeStop();
193   return Serializable::From(std::move(owned_bytes_));
194 }
195 
Deserialize(DeserializerState * state,double * value)196 bool ProtocolTypeTraits<double>::Deserialize(DeserializerState* state,
197                                              double* value) {
198   // Double values that round-trip through JSON may end up getting represented
199   // as an int32 (SIGNED, UNSIGNED) on the wire in CBOR. Therefore, we also
200   // accept an INT32 here.
201   if (state->tokenizer()->TokenTag() == cbor::CBORTokenTag::INT32) {
202     *value = state->tokenizer()->GetInt32();
203     return true;
204   }
205   if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::DOUBLE) {
206     state->RegisterError(Error::BINDINGS_DOUBLE_VALUE_EXPECTED);
207     return false;
208   }
209   *value = state->tokenizer()->GetDouble();
210   return true;
211 }
212 
Serialize(double value,std::vector<uint8_t> * bytes)213 void ProtocolTypeTraits<double>::Serialize(double value,
214                                            std::vector<uint8_t>* bytes) {
215   cbor::EncodeDouble(value, bytes);
216 }
217 
218 class IncomingDeferredMessage : public DeferredMessage {
219  public:
220   // Creates the state from the part of another message.
221   // Note storage is opaque and is mostly to retain ownership.
222   // It may be null in case caller owns the memory and will dispose
223   // of the message synchronously.
IncomingDeferredMessage(DeserializerState::Storage storage,span<uint8_t> span)224   IncomingDeferredMessage(DeserializerState::Storage storage,
225                           span<uint8_t> span)
226       : storage_(storage), span_(span) {}
227 
228  private:
MakeDeserializer() const229   DeserializerState MakeDeserializer() const override {
230     return DeserializerState(storage_, span_);
231   }
AppendSerialized(std::vector<uint8_t> * out) const232   void AppendSerialized(std::vector<uint8_t>* out) const override {
233     out->insert(out->end(), span_.begin(), span_.end());
234   }
235 
236   DeserializerState::Storage storage_;
237   span<uint8_t> span_;
238 };
239 
240 class OutgoingDeferredMessage : public DeferredMessage {
241  public:
242   OutgoingDeferredMessage() = default;
OutgoingDeferredMessage(std::unique_ptr<Serializable> serializable)243   explicit OutgoingDeferredMessage(std::unique_ptr<Serializable> serializable)
244       : serializable_(std::move(serializable)) {
245     assert(!!serializable_);
246   }
247 
248  private:
MakeDeserializer() const249   DeserializerState MakeDeserializer() const override {
250     return DeserializerState(serializable_->Serialize());
251   }
AppendSerialized(std::vector<uint8_t> * out) const252   void AppendSerialized(std::vector<uint8_t>* out) const override {
253     serializable_->AppendSerialized(out);
254   }
255 
256   std::unique_ptr<Serializable> serializable_;
257 };
258 
259 // static
FromSerializable(std::unique_ptr<Serializable> serializeable)260 std::unique_ptr<DeferredMessage> DeferredMessage::FromSerializable(
261     std::unique_ptr<Serializable> serializeable) {
262   return std::make_unique<OutgoingDeferredMessage>(std::move(serializeable));
263 }
264 
265 // static
FromSpan(span<uint8_t> bytes)266 std::unique_ptr<DeferredMessage> DeferredMessage::FromSpan(
267     span<uint8_t> bytes) {
268   return std::make_unique<IncomingDeferredMessage>(nullptr, bytes);
269 }
270 
Deserialize(DeserializerState * state,std::unique_ptr<DeferredMessage> * value)271 bool ProtocolTypeTraits<std::unique_ptr<DeferredMessage>>::Deserialize(
272     DeserializerState* state,
273     std::unique_ptr<DeferredMessage>* value) {
274   if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::ENVELOPE) {
275     state->RegisterError(Error::CBOR_INVALID_ENVELOPE);
276     return false;
277   }
278   *value = std::make_unique<IncomingDeferredMessage>(
279       state->storage(), state->tokenizer()->GetEnvelope());
280   return true;
281 }
282 
Serialize(const std::unique_ptr<DeferredMessage> & value,std::vector<uint8_t> * bytes)283 void ProtocolTypeTraits<std::unique_ptr<DeferredMessage>>::Serialize(
284     const std::unique_ptr<DeferredMessage>& value,
285     std::vector<uint8_t>* bytes) {
286   value->AppendSerialized(bytes);
287 }
288 
289 }  // namespace v8_crdtp
290