protocol_core.cc 9.4 KB

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